Commit 71626568e01ad3d6ee73d63de976d6012cd46066
1 parent
bb4fa27c
Exists in
master
and in
19 other branches
make includes per model separate option, updated readme
Showing
5 changed files
with
42 additions
and
12 deletions
Show diff stats
README.md
... | ... | @@ -1630,6 +1630,13 @@ Eager load associations |
1630 | 1630 | Product.search "milk", includes: [:brand, :stores] |
1631 | 1631 | ``` |
1632 | 1632 | |
1633 | +Load associations per model | |
1634 | + | |
1635 | +```ruby | |
1636 | +Searchkick.search("*", index_name: [Product.search_index.name, Discount.search_index.name], includes_per: {Product => :store, Discount => :product}) | |
1637 | +``` | |
1638 | +These 2 options above can be combined, but you should make sure that associations specified by `includes` present in all searched models | |
1639 | + | |
1633 | 1640 | Turn off special characters |
1634 | 1641 | |
1635 | 1642 | ```ruby | ... | ... |
lib/searchkick/query.rb
... | ... | @@ -17,7 +17,7 @@ module Searchkick |
17 | 17 | def initialize(klass, term = "*", **options) |
18 | 18 | unknown_keywords = options.keys - [:aggs, :body, :body_options, :boost, |
19 | 19 | :boost_by, :boost_by_distance, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain, |
20 | - :fields, :highlight, :includes, :index_name, :indices_boost, :limit, :load, | |
20 | + :fields, :highlight, :includes, :includes_per, :index_name, :indices_boost, :limit, :load, | |
21 | 21 | :match, :misspellings, :offset, :operator, :order, :padding, :page, :per_page, :profile, |
22 | 22 | :request_params, :routing, :select, :similar, :smart_aggs, :suggest, :track, :type, :where] |
23 | 23 | raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any? |
... | ... | @@ -108,6 +108,7 @@ module Searchkick |
108 | 108 | padding: @padding, |
109 | 109 | load: @load, |
110 | 110 | includes: options[:includes], |
111 | + includes_per: options[:includes_per], | |
111 | 112 | json: !@json.nil?, |
112 | 113 | match_suffix: @match_suffix, |
113 | 114 | highlighted_fields: @highlighted_fields || [], | ... | ... |
lib/searchkick/results.rb
... | ... | @@ -198,13 +198,13 @@ module Searchkick |
198 | 198 | |
199 | 199 | def results_query(records, hits) |
200 | 200 | ids = hits.map { |hit| hit["_id"] } |
201 | - if options[:includes] | |
201 | + if (options[:includes] || options[:includes_per]) | |
202 | 202 | |
203 | - included_relations = if options[:includes].is_a? Hash | |
204 | - options[:includes][records] | |
205 | - else | |
206 | - options[:includes] | |
207 | - end | |
203 | + | |
204 | + included_relations = [] | |
205 | + | |
206 | + included_relations << options[:includes] if options[:includes] | |
207 | + included_relations << options[:includes_per][records] if (options[:includes_per] && options[:includes_per][records]) | |
208 | 208 | |
209 | 209 | records = |
210 | 210 | if defined?(NoBrainer::Document) && records < NoBrainer::Document | ... | ... |
test/sql_test.rb
... | ... | @@ -195,19 +195,35 @@ class SqlTest < Minitest::Test |
195 | 195 | assert Product.search("product", includes: [:store]).first.association(:store).loaded? |
196 | 196 | end |
197 | 197 | |
198 | - def test_includes_per_model | |
198 | + def test_includes_per | |
199 | 199 | skip unless defined?(ActiveRecord) |
200 | 200 | store_names ["Product A"] |
201 | 201 | store_names ['Product A Discount'], Discount |
202 | 202 | |
203 | - associations = {Product => :store, Discount => :product} | |
203 | + associations = { Product => :store, Discount => :product } | |
204 | 204 | |
205 | - result = Searchkick.search("product", fields: [:name], index_name: [Product.search_index.name, Discount.search_index.name], includes: associations) | |
206 | - | |
207 | - assert_equal 2, result.length | |
205 | + result = Searchkick.search("product", fields: [:name], index_name: [Product.search_index.name, Discount.search_index.name], includes_per: associations) | |
208 | 206 | |
209 | 207 | result.group_by(&:class).each_pair do |klass, records| |
210 | 208 | assert records.first.association(associations[klass]).loaded? |
211 | 209 | end |
212 | 210 | end |
211 | + | |
212 | + def test_both_includes | |
213 | + skip unless defined?(ActiveRecord) | |
214 | + store_names ["Product A"] | |
215 | + store_names ['Product A Discount'], Discount | |
216 | + | |
217 | + associations = { Discount => :product } | |
218 | + | |
219 | + result = Searchkick.search("product", fields: [:name], index_name: [Product.search_index.name, Discount.search_index.name], includes: [:store], includes_per: associations) | |
220 | + | |
221 | + assert_equal 2, result.length | |
222 | + | |
223 | + assert result.find{|record| record.class == Product}.association(:store).loaded? | |
224 | + assert result.find{|record| record.class == Discount}.association(:store).loaded? | |
225 | + assert result.find{|record| record.class == Discount}.association(:product).loaded? | |
226 | + end | |
227 | + | |
228 | + | |
213 | 229 | end | ... | ... |
test/test_helper.rb
... | ... | @@ -87,6 +87,7 @@ if defined?(Mongoid) |
87 | 87 | class Discount |
88 | 88 | include Mongoid::Document |
89 | 89 | belongs_to :product |
90 | + belongs_to :store | |
90 | 91 | |
91 | 92 | field :name |
92 | 93 | end |
... | ... | @@ -161,6 +162,8 @@ elsif defined?(NoBrainer) |
161 | 162 | field :name, type: String |
162 | 163 | |
163 | 164 | belongs_to :product, validates: false |
165 | + belongs_to :store, validates: false | |
166 | + | |
164 | 167 | end |
165 | 168 | |
166 | 169 | |
... | ... | @@ -372,6 +375,7 @@ else |
372 | 375 | ActiveRecord::Migration.create_table :discounts do |t| |
373 | 376 | t.string :name |
374 | 377 | t.integer :product_id |
378 | + t.integer :store_id | |
375 | 379 | end |
376 | 380 | |
377 | 381 | ActiveRecord::Migration.create_table :stores do |t| |
... | ... | @@ -404,6 +408,7 @@ else |
404 | 408 | |
405 | 409 | class Discount < ActiveRecord::Base |
406 | 410 | belongs_to :product |
411 | + belongs_to :store | |
407 | 412 | end |
408 | 413 | |
409 | 414 | class Store < ActiveRecord::Base |
... | ... | @@ -585,6 +590,7 @@ class Minitest::Test |
585 | 590 | def setup |
586 | 591 | Product.destroy_all |
587 | 592 | Store.destroy_all |
593 | + Discount.destroy_all | |
588 | 594 | Animal.destroy_all |
589 | 595 | Speaker.destroy_all |
590 | 596 | Sku.destroy_all | ... | ... |