Commit 329e05353fe8a16822832a910d16cadc475ef38c
1 parent
69cf12cf
Exists in
master
and in
2 other branches
Use lazy loading for searches [skip ci]
Showing
6 changed files
with
64 additions
and
10 deletions
Show diff stats
CHANGELOG.md
README.md
... | ... | @@ -2053,6 +2053,18 @@ gem "elasticsearch" |
2053 | 2053 | |
2054 | 2054 | If using the deprecated `faraday_middleware-aws-signers-v4` gem, switch to `faraday_middleware-aws-sigv4`. |
2055 | 2055 | |
2056 | +Also, searches now use lazy loading: | |
2057 | + | |
2058 | +```ruby | |
2059 | +# search not executed | |
2060 | +products = Product.search("milk") | |
2061 | + | |
2062 | +# search executed | |
2063 | +products.each do |product| | |
2064 | + # ... | |
2065 | +end | |
2066 | +``` | |
2067 | + | |
2056 | 2068 | Check out the [changelog](https://github.com/ankane/searchkick/blob/master/CHANGELOG.md) for the full list of changes. |
2057 | 2069 | |
2058 | 2070 | ## History | ... | ... |
lib/searchkick.rb
... | ... | @@ -15,6 +15,7 @@ require "searchkick/query" |
15 | 15 | require "searchkick/reindex_queue" |
16 | 16 | require "searchkick/record_data" |
17 | 17 | require "searchkick/record_indexer" |
18 | +require "searchkick/relation" | |
18 | 19 | require "searchkick/results" |
19 | 20 | require "searchkick/version" |
20 | 21 | |
... | ... | @@ -150,16 +151,18 @@ module Searchkick |
150 | 151 | end |
151 | 152 | end |
152 | 153 | |
153 | - options = options.merge(block: block) if block | |
154 | - query = Searchkick::Query.new(klass, term, **options) | |
154 | + # TODO remove in Searchkick 6.0 | |
155 | 155 | if options[:execute] == false |
156 | - query | |
157 | - else | |
158 | - query.execute | |
156 | + Searchkick.warn("The execute option is no longer needed") | |
157 | + options.delete(:execute) | |
159 | 158 | end |
159 | + | |
160 | + options = options.merge(block: block) if block | |
161 | + Searchkick::Relation.new(klass, term, **options) | |
160 | 162 | end |
161 | 163 | |
162 | 164 | def self.multi_search(queries) |
165 | + queries = queries.map { |q| q.send(:query) } | |
163 | 166 | Searchkick::MultiSearch.new(queries).perform |
164 | 167 | end |
165 | 168 | ... | ... |
lib/searchkick/query.rb
... | ... | @@ -18,7 +18,7 @@ module Searchkick |
18 | 18 | |
19 | 19 | def initialize(klass, term = "*", **options) |
20 | 20 | unknown_keywords = options.keys - [:aggs, :block, :body, :body_options, :boost, |
21 | - :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain, | |
21 | + :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :explain, | |
22 | 22 | :fields, :highlight, :includes, :index_name, :indices_boost, :limit, :load, |
23 | 23 | :match, :misspellings, :models, :model_includes, :offset, :operator, :order, :padding, :page, :per_page, :profile, |
24 | 24 | :request_params, :routing, :scope_results, :scroll, :select, :similar, :smart_aggs, :suggest, :total_entries, :track, :type, :where] | ... | ... |
... | ... | @@ -0,0 +1,38 @@ |
1 | +require "active_support/core_ext/module/delegation" | |
2 | + | |
3 | +module Searchkick | |
4 | + class Relation | |
5 | + # note: modifying body directly is not supported | |
6 | + # and has no impact on query after being executed | |
7 | + # TODO freeze body object? | |
8 | + delegate :body, :params, to: :@query | |
9 | + delegate_missing_to :private_execute | |
10 | + | |
11 | + def initialize(klass, term = "*", **options) | |
12 | + @query = Query.new(klass, term, **options) | |
13 | + end | |
14 | + | |
15 | + # same as Active Record | |
16 | + def inspect | |
17 | + entries = results.first(11).map!(&:inspect) | |
18 | + entries[10] = "..." if entries.size == 11 | |
19 | + "#<#{self.class.name} [#{entries.join(', ')}]>" | |
20 | + end | |
21 | + | |
22 | + def execute | |
23 | + Searchkick.warn("The execute method is no longer needed") | |
24 | + private_execute | |
25 | + self | |
26 | + end | |
27 | + | |
28 | + private | |
29 | + | |
30 | + def private_execute | |
31 | + @execute ||= @query.execute | |
32 | + end | |
33 | + | |
34 | + def query | |
35 | + @query | |
36 | + end | |
37 | + end | |
38 | +end | ... | ... |
test/search_test.rb
... | ... | @@ -56,14 +56,14 @@ class SearchTest < Minitest::Test |
56 | 56 | def test_bad_mapping |
57 | 57 | Product.searchkick_index.delete |
58 | 58 | store_names ["Product A"] |
59 | - error = assert_raises(Searchkick::InvalidQueryError) { Product.search "test" } | |
59 | + error = assert_raises(Searchkick::InvalidQueryError) { Product.search("test").to_a } | |
60 | 60 | assert_equal "Bad mapping - run Product.reindex", error.message |
61 | 61 | ensure |
62 | 62 | Product.reindex |
63 | 63 | end |
64 | 64 | |
65 | 65 | def test_missing_index |
66 | - assert_raises(Searchkick::MissingIndexError) { Product.search("test", index_name: "not_found") } | |
66 | + assert_raises(Searchkick::MissingIndexError) { Product.search("test", index_name: "not_found").to_a } | |
67 | 67 | end |
68 | 68 | |
69 | 69 | def test_unsupported_version |
... | ... | @@ -77,11 +77,11 @@ class SearchTest < Minitest::Test |
77 | 77 | end |
78 | 78 | end |
79 | 79 | Searchkick.client.stub :search, raises_exception do |
80 | - assert_raises(Searchkick::UnsupportedVersionError) { Product.search("test") } | |
80 | + assert_raises(Searchkick::UnsupportedVersionError) { Product.search("test").to_a } | |
81 | 81 | end |
82 | 82 | end |
83 | 83 | |
84 | 84 | def test_invalid_body |
85 | - assert_raises(Searchkick::InvalidQueryError) { Product.search(body: {boom: true}) } | |
85 | + assert_raises(Searchkick::InvalidQueryError) { Product.search(body: {boom: true}).to_a } | |
86 | 86 | end |
87 | 87 | end | ... | ... |