Commit 2c9a0cb27384ce199e6a3725f1920873d8a207fa
1 parent
c6e369a3
Exists in
master
and in
21 other branches
Return ActiveRecord objects
Showing
3 changed files
with
106 additions
and
101 deletions
Show diff stats
lib/searchkick/reindex.rb
@@ -12,11 +12,11 @@ module Searchkick | @@ -12,11 +12,11 @@ module Searchkick | ||
12 | # use scope for import | 12 | # use scope for import |
13 | scope = respond_to?(:searchkick_import) ? searchkick_import : self | 13 | scope = respond_to?(:searchkick_import) ? searchkick_import : self |
14 | scope.find_in_batches do |batch| | 14 | scope.find_in_batches do |batch| |
15 | - tire.index.import batch | 15 | + index.import batch |
16 | end | 16 | end |
17 | 17 | ||
18 | if a = Tire::Alias.find(alias_name) | 18 | if a = Tire::Alias.find(alias_name) |
19 | - old_indices = Tire::Alias.find(alias_name).indices | 19 | + old_indices = a.indices.dup |
20 | old_indices.each do |index| | 20 | old_indices.each do |index| |
21 | a.indices.delete index | 21 | a.indices.delete index |
22 | end | 22 | end |
@@ -26,7 +26,7 @@ module Searchkick | @@ -26,7 +26,7 @@ module Searchkick | ||
26 | 26 | ||
27 | old_indices.each do |index| | 27 | old_indices.each do |index| |
28 | i = Tire::Index.new(index) | 28 | i = Tire::Index.new(index) |
29 | - i.delete if i.exists? | 29 | + i.delete |
30 | end | 30 | end |
31 | else | 31 | else |
32 | i = Tire::Index.new(alias_name) | 32 | i = Tire::Index.new(alias_name) |
lib/searchkick/search.rb
@@ -8,131 +8,135 @@ module Searchkick | @@ -8,131 +8,135 @@ module Searchkick | ||
8 | def search(term, options = {}) | 8 | def search(term, options = {}) |
9 | fields = options[:fields] || ["_all"] | 9 | fields = options[:fields] || ["_all"] |
10 | operator = options[:partial] ? "or" : "and" | 10 | operator = options[:partial] ? "or" : "and" |
11 | - tire.search load: true do | ||
12 | - query do | ||
13 | - boolean do | ||
14 | - must do | ||
15 | - dis_max do | ||
16 | - query do | ||
17 | - match fields, term, boost: 10, operator: operator, analyzer: "searchkick_search" | ||
18 | - end | ||
19 | - query do | ||
20 | - match fields, term, boost: 10, operator: operator, analyzer: "searchkick_search2" | ||
21 | - end | ||
22 | - query do | ||
23 | - match fields, term, use_dis_max: false, fuzziness: 0.7, max_expansions: 1, prefix_length: 1, operator: operator, analyzer: "searchkick_search" | ||
24 | - end | ||
25 | - query do | ||
26 | - match fields, term, use_dis_max: false, fuzziness: 0.7, max_expansions: 1, prefix_length: 1, operator: operator, analyzer: "searchkick_search2" | 11 | + results = |
12 | + tire.search do | ||
13 | + query do | ||
14 | + boolean do | ||
15 | + must do | ||
16 | + dis_max do | ||
17 | + query do | ||
18 | + match fields, term, boost: 10, operator: operator, analyzer: "searchkick_search" | ||
19 | + end | ||
20 | + query do | ||
21 | + match fields, term, boost: 10, operator: operator, analyzer: "searchkick_search2" | ||
22 | + end | ||
23 | + query do | ||
24 | + match fields, term, use_dis_max: false, fuzziness: 0.7, max_expansions: 1, prefix_length: 1, operator: operator, analyzer: "searchkick_search" | ||
25 | + end | ||
26 | + query do | ||
27 | + match fields, term, use_dis_max: false, fuzziness: 0.7, max_expansions: 1, prefix_length: 1, operator: operator, analyzer: "searchkick_search2" | ||
28 | + end | ||
27 | end | 29 | end |
28 | end | 30 | end |
29 | - end | ||
30 | - if options[:conversions] | ||
31 | - should do | ||
32 | - nested path: "conversions", score_mode: "total" do | ||
33 | - query do | ||
34 | - custom_score script: "log(doc['count'].value)" do | ||
35 | - match "query", term | 31 | + if options[:conversions] |
32 | + should do | ||
33 | + nested path: "conversions", score_mode: "total" do | ||
34 | + query do | ||
35 | + custom_score script: "log(doc['count'].value)" do | ||
36 | + match "query", term | ||
37 | + end | ||
36 | end | 38 | end |
37 | end | 39 | end |
38 | end | 40 | end |
39 | end | 41 | end |
40 | end | 42 | end |
41 | end | 43 | end |
42 | - end | ||
43 | - # fields "_id", "_type", "name" # only return _id and _type - http://www.elasticsearch.org/guide/reference/api/search/fields/ | ||
44 | - size options[:limit] || 100000 # return all - like sql query | ||
45 | - from options[:offset] if options[:offset] | ||
46 | - explain options[:explain] if options[:explain] | 44 | + # fields "_id", "_type", "name" # only return _id and _type - http://www.elasticsearch.org/guide/reference/api/search/fields/ |
45 | + size options[:limit] || 100000 # return all - like sql query | ||
46 | + from options[:offset] if options[:offset] | ||
47 | + explain options[:explain] if options[:explain] | ||
47 | 48 | ||
48 | - # order | ||
49 | - if options[:order] | ||
50 | - sort do | ||
51 | - options[:order].each do |k, v| | ||
52 | - by k, v | 49 | + # order |
50 | + if options[:order] | ||
51 | + sort do | ||
52 | + options[:order].each do |k, v| | ||
53 | + by k, v | ||
54 | + end | ||
53 | end | 55 | end |
54 | end | 56 | end |
55 | - end | ||
56 | 57 | ||
57 | - # where | ||
58 | - # TODO expand or | 58 | + # where |
59 | + # TODO expand or | ||
59 | 60 | ||
60 | - where_filters = | ||
61 | - proc do |where| | ||
62 | - filters = [] | ||
63 | - (where || {}).each do |field, value| | ||
64 | - if field == :or | ||
65 | - value.each do |or_clause| | ||
66 | - filters << {or: or_clause.map{|or_statement| {term: or_statement} }} | ||
67 | - end | ||
68 | - else | ||
69 | - # expand ranges | ||
70 | - if value.is_a?(Range) | ||
71 | - value = {gte: value.first, (value.exclude_end? ? :lt : :lte) => value.last} | ||
72 | - end | 61 | + where_filters = |
62 | + proc do |where| | ||
63 | + filters = [] | ||
64 | + (where || {}).each do |field, value| | ||
65 | + if field == :or | ||
66 | + value.each do |or_clause| | ||
67 | + filters << {or: or_clause.map{|or_statement| {term: or_statement} }} | ||
68 | + end | ||
69 | + else | ||
70 | + # expand ranges | ||
71 | + if value.is_a?(Range) | ||
72 | + value = {gte: value.first, (value.exclude_end? ? :lt : :lte) => value.last} | ||
73 | + end | ||
73 | 74 | ||
74 | - if value.is_a?(Array) # in query | ||
75 | - filters << {terms: {field => value}} | ||
76 | - elsif value.is_a?(Hash) | ||
77 | - value.each do |op, op_value| | ||
78 | - if op == :not # not equal | ||
79 | - if op_value.is_a?(Array) | ||
80 | - filters << {not: {terms: {field => op_value}}} | ||
81 | - else | ||
82 | - filters << {not: {term: {field => op_value}}} | ||
83 | - end | ||
84 | - else | ||
85 | - range_query = | ||
86 | - case op | ||
87 | - when :gt | ||
88 | - {from: op_value, include_lower: false} | ||
89 | - when :gte | ||
90 | - {from: op_value, include_lower: true} | ||
91 | - when :lt | ||
92 | - {to: op_value, include_upper: false} | ||
93 | - when :lte | ||
94 | - {to: op_value, include_upper: true} | 75 | + if value.is_a?(Array) # in query |
76 | + filters << {terms: {field => value}} | ||
77 | + elsif value.is_a?(Hash) | ||
78 | + value.each do |op, op_value| | ||
79 | + if op == :not # not equal | ||
80 | + if op_value.is_a?(Array) | ||
81 | + filters << {not: {terms: {field => op_value}}} | ||
95 | else | 82 | else |
96 | - raise "Unknown where operator" | 83 | + filters << {not: {term: {field => op_value}}} |
97 | end | 84 | end |
98 | - filters << {range: {field => range_query}} | 85 | + else |
86 | + range_query = | ||
87 | + case op | ||
88 | + when :gt | ||
89 | + {from: op_value, include_lower: false} | ||
90 | + when :gte | ||
91 | + {from: op_value, include_lower: true} | ||
92 | + when :lt | ||
93 | + {to: op_value, include_upper: false} | ||
94 | + when :lte | ||
95 | + {to: op_value, include_upper: true} | ||
96 | + else | ||
97 | + raise "Unknown where operator" | ||
98 | + end | ||
99 | + filters << {range: {field => range_query}} | ||
100 | + end | ||
99 | end | 101 | end |
102 | + else | ||
103 | + filters << {term: {field => value}} | ||
100 | end | 104 | end |
101 | - else | ||
102 | - filters << {term: {field => value}} | ||
103 | end | 105 | end |
104 | end | 106 | end |
107 | + filters | ||
105 | end | 108 | end |
106 | - filters | ||
107 | - end | ||
108 | - | ||
109 | - where_filters.call(options[:where]).each do |f| | ||
110 | - type, value = f.first | ||
111 | - filter type, value | ||
112 | - end | ||
113 | 109 | ||
114 | - # facets | ||
115 | - if options[:facets] | ||
116 | - facets = options[:facets] || {} | ||
117 | - if facets.is_a?(Array) # convert to more advanced syntax | ||
118 | - facets = Hash[ facets.map{|f| [f, {}] } ] | 110 | + where_filters.call(options[:where]).each do |f| |
111 | + type, value = f.first | ||
112 | + filter type, value | ||
119 | end | 113 | end |
120 | 114 | ||
121 | - facets.each do |field, facet_options| | ||
122 | - facet_filters = where_filters.call(facet_options[:where]) | ||
123 | - facet field do | ||
124 | - terms field | ||
125 | - if facet_filters.size == 1 | ||
126 | - type, value = facet_filters.first.first | ||
127 | - facet_filter type, value | ||
128 | - elsif facet_filters.size > 1 | ||
129 | - facet_filter :and, *facet_filters | 115 | + # facets |
116 | + if options[:facets] | ||
117 | + facets = options[:facets] || {} | ||
118 | + if facets.is_a?(Array) # convert to more advanced syntax | ||
119 | + facets = Hash[ facets.map{|f| [f, {}] } ] | ||
120 | + end | ||
121 | + | ||
122 | + facets.each do |field, facet_options| | ||
123 | + facet_filters = where_filters.call(facet_options[:where]) | ||
124 | + facet field do | ||
125 | + terms field | ||
126 | + if facet_filters.size == 1 | ||
127 | + type, value = facet_filters.first.first | ||
128 | + facet_filter type, value | ||
129 | + elsif facet_filters.size > 1 | ||
130 | + facet_filter :and, *facet_filters | ||
131 | + end | ||
130 | end | 132 | end |
131 | end | 133 | end |
132 | end | 134 | end |
133 | end | 135 | end |
134 | 136 | ||
135 | - end | 137 | + result_ids = results.map(&:id) |
138 | + models = Hash[ find(result_ids).map{|m| [m.id.to_s, m] } ] | ||
139 | + result_ids.map{|id| models[id] }.compact | ||
136 | end | 140 | end |
137 | end | 141 | end |
138 | end | 142 | end |
test/searchkick_test.rb
@@ -22,11 +22,12 @@ class Product < ActiveRecord::Base | @@ -22,11 +22,12 @@ class Product < ActiveRecord::Base | ||
22 | end | 22 | end |
23 | end | 23 | end |
24 | 24 | ||
25 | +Product.reindex | ||
26 | + | ||
25 | class TestSearchkick < Minitest::Unit::TestCase | 27 | class TestSearchkick < Minitest::Unit::TestCase |
26 | 28 | ||
27 | def setup | 29 | def setup |
28 | - Product.index.delete | ||
29 | - Product.reindex | 30 | + Product.destroy_all |
30 | end | 31 | end |
31 | 32 | ||
32 | # exact | 33 | # exact |