Avoid duplicated queries and, instead, bump the last ones
This commit is contained in:
@@ -3,6 +3,6 @@ class SearchesController < ApplicationController
|
||||
|
||||
def show
|
||||
@search_results = Current.user.search(@query_terms).limit(50)
|
||||
@recent_search_queries = Current.user.search_queries.order(created_at: :desc).limit(50).uniq(&:terms)
|
||||
@recent_search_queries = Current.user.search_queries.order(updated_at: :desc).limit(10)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,8 @@ module User::Searcher
|
||||
end
|
||||
|
||||
def remember_search(terms)
|
||||
search_queries.create(terms: terms) if search_queries.last&.terms != terms
|
||||
search_queries.find_or_create_by(terms: terms).tap do |search_query|
|
||||
search_query.touch unless search_query.previously_new_record?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddIndexToSearchQueries < ActiveRecord::Migration[8.1]
|
||||
def change
|
||||
add_index :search_queries, %w[ user_id updated_at ], unique: true
|
||||
end
|
||||
end
|
||||
Generated
+2
-1
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.1].define(version: 2025_07_02_211937) do
|
||||
ActiveRecord::Schema[8.1].define(version: 2025_07_03_193928) do
|
||||
create_table "accesses", force: :cascade do |t|
|
||||
t.datetime "accessed_at"
|
||||
t.integer "collection_id", null: false
|
||||
@@ -315,6 +315,7 @@ ActiveRecord::Schema[8.1].define(version: 2025_07_02_211937) do
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.index ["user_id", "terms"], name: "index_search_queries_on_user_id_and_terms"
|
||||
t.index ["user_id", "updated_at"], name: "index_search_queries_on_user_id_and_updated_at", unique: true
|
||||
t.index ["user_id"], name: "index_search_queries_on_user_id"
|
||||
end
|
||||
|
||||
|
||||
+18
-1
@@ -2312,6 +2312,23 @@ indexes:
|
||||
nulls_not_distinct:
|
||||
comment:
|
||||
valid: true
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
|
||||
table: search_queries
|
||||
name: index_search_queries_on_user_id_and_updated_at
|
||||
unique: true
|
||||
columns:
|
||||
- user_id
|
||||
- updated_at
|
||||
lengths: {}
|
||||
orders: {}
|
||||
opclasses: {}
|
||||
where:
|
||||
type:
|
||||
using:
|
||||
include:
|
||||
nulls_not_distinct:
|
||||
comment:
|
||||
valid: true
|
||||
search_results: []
|
||||
sessions:
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
|
||||
@@ -2499,4 +2516,4 @@ indexes:
|
||||
comment:
|
||||
valid: true
|
||||
workflows: []
|
||||
version: 20250702211937
|
||||
version: 20250703193928
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require_relative "../config/environment"
|
||||
|
||||
ApplicationRecord.with_each_tenant do |tenant|
|
||||
User.find_each do |user|
|
||||
search_queries = Set.new
|
||||
to_delete = []
|
||||
user.search_queries.find_each do |search_query|
|
||||
if search_queries.include?(search_query.terms)
|
||||
to_delete << search_query
|
||||
end
|
||||
|
||||
search_queries << search_query.terms
|
||||
end
|
||||
|
||||
to_delete.each(&:destroy)
|
||||
end
|
||||
end
|
||||
@@ -13,11 +13,16 @@ class User::SearcherTest < ActiveSupport::TestCase
|
||||
assert_equal "broken", @user.search_queries.last.terms
|
||||
end
|
||||
|
||||
test "don't duplicate repeated searches" do
|
||||
@user.remember_search("broken")
|
||||
test "don't duplicate repeated searches but touch the existing match" do
|
||||
search_result = @user.remember_search("broken")
|
||||
original_updated_at = search_result.updated_at
|
||||
|
||||
travel_to 1.day.from_now
|
||||
|
||||
assert_no_difference -> { @user.search_queries.count }, +1 do
|
||||
@user.remember_search("broken")
|
||||
end
|
||||
|
||||
assert search_result.reload.updated_at > original_updated_at
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user