Skip to content

Commit 79f97e2

Browse files
committed
Add support for custom search_document_id with record loading
When a model defines a custom search_document_id, searching with load: true would fail to find records because Searchkick used the custom ID to query the database primary key. This adds support for models to define find_by_search_document_ids class method to handle the mapping from custom search document IDs back to database records. Example: class Product < ApplicationRecord searchkick def search_document_id "tenant_#{tenant_id}_#{id}" end def self.find_by_search_document_ids(search_ids) ids = search_ids.map { |sid| sid.split("_").last } where(id: ids) end end Fixes #1732
1 parent 107d270 commit 79f97e2

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

lib/searchkick/results.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def with_hit_and_missing_records
248248
grouped_hits.each do |index, index_hits|
249249
results[index] = {}
250250
index_models[index].each do |model|
251-
results[index].merge!(results_query(model, index_hits).to_a.index_by { |r| r.id.to_s })
251+
results[index].merge!(results_query(model, index_hits).to_a.index_by { |r| record_search_id(r) })
252252
end
253253
end
254254

@@ -331,7 +331,11 @@ def results_query(records, hits)
331331
records = options[:scope_results].call(records)
332332
end
333333

334-
Searchkick.load_records(records, ids)
334+
if records.respond_to?(:find_by_search_document_ids)
335+
records.find_by_search_document_ids(ids)
336+
else
337+
Searchkick.load_records(records, ids)
338+
end
335339
end
336340

337341
def combine_includes(result, inc)
@@ -344,6 +348,11 @@ def combine_includes(result, inc)
344348
end
345349
end
346350

351+
def record_search_id(record)
352+
id = record.respond_to?(:search_document_id) ? record.search_document_id : record.id
353+
id.to_s
354+
end
355+
347356
def base_field(k)
348357
k.sub(/\.(analyzed|word_start|word_middle|word_end|text_start|text_middle|text_end|exact)\z/, "")
349358
end

test/search_document_id_test.rb

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
require_relative "test_helper"
2+
3+
class SearchDocumentIdTest < Minitest::Test
4+
def test_custom_search_document_id_with_find_by_search_document_ids
5+
skip "ActiveRecord only" if mongoid?
6+
7+
# Define custom search_document_id on Product
8+
Product.class_eval do
9+
def search_document_id
10+
"custom_#{id}"
11+
end
12+
13+
def self.find_by_search_document_ids(search_ids)
14+
ids = search_ids.map { |sid| sid.sub(/^custom_/, "") }
15+
where(id: ids)
16+
end
17+
end
18+
19+
begin
20+
Product.reindex
21+
22+
store_names ["Product A", "Product B"]
23+
24+
# Test that search with load: true works
25+
results = Product.search("product").to_a
26+
assert_equal 2, results.size
27+
assert_kind_of Product, results.first
28+
assert_includes ["Product A", "Product B"], results.first.name
29+
assert_includes ["Product A", "Product B"], results.last.name
30+
ensure
31+
# Clean up - remove the custom methods
32+
Product.class_eval do
33+
undef_method :search_document_id if method_defined?(:search_document_id)
34+
35+
class << self
36+
undef_method :find_by_search_document_ids if method_defined?(:find_by_search_document_ids)
37+
end
38+
end
39+
40+
Product.reindex
41+
end
42+
end
43+
44+
def test_custom_search_document_id_without_find_by_search_document_ids_shows_missing_records
45+
skip "ActiveRecord only" if mongoid?
46+
47+
# Define custom search_document_id on Product but NOT find_by_search_document_ids
48+
Product.class_eval do
49+
def search_document_id
50+
"custom_#{id}"
51+
end
52+
end
53+
54+
begin
55+
Product.reindex
56+
57+
store_names ["Product A"]
58+
59+
# Without find_by_search_document_ids, records should be reported as missing
60+
assert_warns "Records in search index do not exist in database" do
61+
results = Product.search("product").to_a
62+
assert_empty results
63+
end
64+
ensure
65+
# Clean up
66+
Product.class_eval do
67+
undef_method :search_document_id if method_defined?(:search_document_id)
68+
end
69+
70+
Product.reindex
71+
end
72+
end
73+
end

0 commit comments

Comments
 (0)