searchkick 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +18 -6
- data/lib/searchkick/reindex.rb +7 -1
- data/lib/searchkick/search.rb +39 -23
- data/lib/searchkick/version.rb +1 -1
- data/test/autocomplete_test.rb +17 -12
- data/test/boost_test.rb +10 -0
- data/test/inheritance_test.rb +13 -0
- data/test/sql_test.rb +20 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b20e3f5f346c6ef75c257cf2b2aafa23884ee2b
|
4
|
+
data.tar.gz: f8c6e426340f0602037a3204e8d38a40d28cf430
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 210eecb919e7491f84acdc1f4f69f2c1bf898b808033ed31f8adc63cc4ac636d0e242cd9136cf1467842aafcd0e358b570b02e9eb0f2e1a7d158807c096e6b3d
|
7
|
+
data.tar.gz: b4907fb7bde4d2a7c13a68b26b84527f8deb00bd41da7216a0637f15f62923f39d0589151edbcd44b1bc0f1eec61e3ae8e5e0be1cc95e440f09b6a694d10f007
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -494,8 +494,9 @@ Dog.reindex # equivalent
|
|
494
494
|
And to search, use:
|
495
495
|
|
496
496
|
```ruby
|
497
|
-
Animal.search "*"
|
498
|
-
Dog.search "*"
|
497
|
+
Animal.search "*" # all animals
|
498
|
+
Dog.search "*" # just dogs
|
499
|
+
Animal.search "*", type: [Dog, Cat] # just cats and dogs [master]
|
499
500
|
```
|
500
501
|
|
501
502
|
**Note:** The `suggest` option retrieves suggestions from the parent at the moment.
|
@@ -747,11 +748,14 @@ For convenience, this is set by default in the test environment.
|
|
747
748
|
|
748
749
|
Thanks to Karel Minarik for [Tire](https://github.com/karmi/tire), Jaroslav Kalistsuk for [zero downtime reindexing](https://gist.github.com/jarosan/3124884), and Alex Leschenko for [Elasticsearch autocomplete](https://github.com/leschenko/elasticsearch_autocomplete).
|
749
750
|
|
750
|
-
##
|
751
|
+
## Roadmap
|
751
752
|
|
752
|
-
-
|
753
|
-
-
|
754
|
-
-
|
753
|
+
- Search multiple fields for different terms
|
754
|
+
- Search across models
|
755
|
+
- Search nested objects
|
756
|
+
- Add section on testing
|
757
|
+
- Much finer customization
|
758
|
+
- More transparency into generated queries (for advanced use)
|
755
759
|
|
756
760
|
## History
|
757
761
|
|
@@ -765,3 +769,11 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
|
|
765
769
|
- Fix bugs and [submit pull requests](https://github.com/ankane/searchkick/pulls)
|
766
770
|
- Write, clarify, or fix documentation
|
767
771
|
- Suggest or add new features
|
772
|
+
|
773
|
+
To get started with development and testing:
|
774
|
+
|
775
|
+
1. Clone the repo
|
776
|
+
2. Install PostgreSQL and create a database called `searchkick_test` (`psql -d postgres -c "create database searchkick_test"`)
|
777
|
+
3. Install Elasticsearch
|
778
|
+
4. `bundle`
|
779
|
+
5. `rake test`
|
data/lib/searchkick/reindex.rb
CHANGED
@@ -51,7 +51,8 @@ module Searchkick
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def self.extended(klass)
|
54
|
-
|
54
|
+
@descendents ||= []
|
55
|
+
@descendents << klass unless @descendents.include?(klass)
|
55
56
|
end
|
56
57
|
|
57
58
|
private
|
@@ -124,6 +125,11 @@ module Searchkick
|
|
124
125
|
tokenizer: "keyword",
|
125
126
|
filter: ["lowercase", "asciifolding"]
|
126
127
|
},
|
128
|
+
searchkick_word_search: {
|
129
|
+
type: "custom",
|
130
|
+
tokenizer: "standard",
|
131
|
+
filter: ["lowercase", "asciifolding"]
|
132
|
+
},
|
127
133
|
searchkick_suggest_index: {
|
128
134
|
type: "custom",
|
129
135
|
tokenizer: "standard",
|
data/lib/searchkick/search.rb
CHANGED
@@ -92,11 +92,12 @@ module Searchkick
|
|
92
92
|
]
|
93
93
|
end
|
94
94
|
else
|
95
|
+
analyzer = field.match(/\.word_(start|middle|end)\z/) ? "searchkick_word_search" : "searchkick_autocomplete_search"
|
95
96
|
queries << {
|
96
97
|
multi_match: {
|
97
98
|
fields: [field],
|
98
99
|
query: term,
|
99
|
-
analyzer:
|
100
|
+
analyzer: analyzer
|
100
101
|
}
|
101
102
|
}
|
102
103
|
end
|
@@ -159,6 +160,15 @@ module Searchkick
|
|
159
160
|
}
|
160
161
|
end
|
161
162
|
|
163
|
+
if options[:personalize]
|
164
|
+
custom_filters << {
|
165
|
+
filter: {
|
166
|
+
term: options[:personalize]
|
167
|
+
},
|
168
|
+
boost: 100
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
162
172
|
if custom_filters.any?
|
163
173
|
payload = {
|
164
174
|
custom_filters_score: {
|
@@ -215,30 +225,29 @@ module Searchkick
|
|
215
225
|
end
|
216
226
|
|
217
227
|
if value.is_a?(Hash)
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
228
|
+
value.each do |op, op_value|
|
229
|
+
case op
|
230
|
+
when :within, :bottom_right
|
231
|
+
# do nothing
|
232
|
+
when :near
|
233
|
+
filters << {
|
234
|
+
geo_distance: {
|
235
|
+
field => op_value.map(&:to_f).reverse,
|
236
|
+
distance: value[:within] || "50mi"
|
237
|
+
}
|
223
238
|
}
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
top_left: value.delete(:top_left).map(&:to_f).reverse,
|
232
|
-
bottom_right: value.delete(:bottom_right).map(&:to_f).reverse
|
239
|
+
when :top_left
|
240
|
+
filters << {
|
241
|
+
geo_bounding_box: {
|
242
|
+
field => {
|
243
|
+
top_left: op_value.map(&:to_f).reverse,
|
244
|
+
bottom_right: value[:bottom_right].map(&:to_f).reverse
|
245
|
+
}
|
233
246
|
}
|
234
247
|
}
|
235
|
-
|
236
|
-
end
|
237
|
-
|
238
|
-
value.each do |op, op_value|
|
239
|
-
if op == :not # not equal
|
248
|
+
when :not # not equal
|
240
249
|
filters << {not: term_filters.call(field, op_value)}
|
241
|
-
|
250
|
+
when :all
|
242
251
|
filters << {terms: {field => op_value, execution: "and"}}
|
243
252
|
else
|
244
253
|
range_query =
|
@@ -254,7 +263,12 @@ module Searchkick
|
|
254
263
|
else
|
255
264
|
raise "Unknown where operator"
|
256
265
|
end
|
257
|
-
|
266
|
+
# issue 132
|
267
|
+
if existing = filters.find{ |f| f[:range] && f[:range][field] }
|
268
|
+
existing[:range][field].merge!(range_query)
|
269
|
+
else
|
270
|
+
filters << {range: {field => range_query}}
|
271
|
+
end
|
258
272
|
end
|
259
273
|
end
|
260
274
|
else
|
@@ -350,7 +364,9 @@ module Searchkick
|
|
350
364
|
payload[:fields] = [] if load
|
351
365
|
|
352
366
|
tire_options = {load: load, payload: payload, size: per_page, from: offset}
|
353
|
-
|
367
|
+
if options[:type] or self != searchkick_klass
|
368
|
+
tire_options[:type] = [options[:type] || self].flatten.map(&:document_type)
|
369
|
+
end
|
354
370
|
search = Tire::Search::Search.new(index_name, tire_options)
|
355
371
|
begin
|
356
372
|
response = search.json
|
data/lib/searchkick/version.rb
CHANGED
data/test/autocomplete_test.rb
CHANGED
@@ -18,33 +18,38 @@ class TestAutocomplete < Minitest::Unit::TestCase
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def test_text_start
|
21
|
-
store_names ["Where in the World is Carmen San Diego
|
22
|
-
assert_search "
|
21
|
+
store_names ["Where in the World is Carmen San Diego"]
|
22
|
+
assert_search "where in the world is", ["Where in the World is Carmen San Diego"], fields: [{name: :text_start}]
|
23
|
+
assert_search "in the world", [], fields: [{name: :text_start}]
|
23
24
|
end
|
24
25
|
|
25
26
|
def test_text_middle
|
26
|
-
store_names ["Where in the World is Carmen San Diego
|
27
|
-
assert_search "
|
27
|
+
store_names ["Where in the World is Carmen San Diego"]
|
28
|
+
assert_search "where in the world is", ["Where in the World is Carmen San Diego"], fields: [{name: :text_middle}]
|
29
|
+
assert_search "n the wor", ["Where in the World is Carmen San Diego"], fields: [{name: :text_middle}]
|
30
|
+
assert_search "men san diego", ["Where in the World is Carmen San Diego"], fields: [{name: :text_middle}]
|
31
|
+
assert_search "world carmen", [], fields: [{name: :text_middle}]
|
28
32
|
end
|
29
33
|
|
30
34
|
def test_text_end
|
31
|
-
store_names ["Where in the World is Carmen San Diego
|
32
|
-
assert_search "
|
35
|
+
store_names ["Where in the World is Carmen San Diego"]
|
36
|
+
assert_search "men san diego", ["Where in the World is Carmen San Diego"], fields: [{name: :text_end}]
|
37
|
+
assert_search "carmen san", [], fields: [{name: :text_end}]
|
33
38
|
end
|
34
39
|
|
35
40
|
def test_word_start
|
36
|
-
store_names ["Where in the World is Carmen San Diego
|
37
|
-
assert_search "car", ["Where in the World is Carmen San Diego
|
41
|
+
store_names ["Where in the World is Carmen San Diego"]
|
42
|
+
assert_search "car san wor", ["Where in the World is Carmen San Diego"], fields: [{name: :word_start}]
|
38
43
|
end
|
39
44
|
|
40
45
|
def test_word_middle
|
41
|
-
store_names ["Where in the World is Carmen San Diego
|
42
|
-
assert_search "orl", ["Where in the World is Carmen San Diego
|
46
|
+
store_names ["Where in the World is Carmen San Diego"]
|
47
|
+
assert_search "orl", ["Where in the World is Carmen San Diego"], fields: [{name: :word_middle}]
|
43
48
|
end
|
44
49
|
|
45
50
|
def test_word_end
|
46
|
-
store_names ["Where in the World is Carmen San Diego
|
47
|
-
assert_search "men", ["Where in the World is Carmen San Diego
|
51
|
+
store_names ["Where in the World is Carmen San Diego"]
|
52
|
+
assert_search "rld men ego", ["Where in the World is Carmen San Diego"], fields: [{name: :word_end}]
|
48
53
|
end
|
49
54
|
|
50
55
|
end
|
data/test/boost_test.rb
CHANGED
@@ -57,4 +57,14 @@ class TestBoost < Minitest::Unit::TestCase
|
|
57
57
|
assert_first "tomato", "Tomato B", user_id: 2
|
58
58
|
end
|
59
59
|
|
60
|
+
def test_personalize
|
61
|
+
store [
|
62
|
+
{name: "Tomato A"},
|
63
|
+
{name: "Tomato B", user_ids: [1, 2, 3]},
|
64
|
+
{name: "Tomato C"},
|
65
|
+
{name: "Tomato D"}
|
66
|
+
]
|
67
|
+
assert_first "tomato", "Tomato B", personalize: {user_ids: 2}
|
68
|
+
end
|
69
|
+
|
60
70
|
end
|
data/test/inheritance_test.rb
CHANGED
@@ -25,6 +25,19 @@ class TestInheritance < Minitest::Unit::TestCase
|
|
25
25
|
assert_equal 2, Animal.search("bear").size
|
26
26
|
end
|
27
27
|
|
28
|
+
def test_force_one_type
|
29
|
+
store_names ["Green Bear"], Dog
|
30
|
+
store_names ["Blue Bear"], Cat
|
31
|
+
assert_equal ["Blue Bear"], Animal.search("bear", type: [Cat]).map(&:name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_force_multiple_types
|
35
|
+
store_names ["Green Bear"], Dog
|
36
|
+
store_names ["Blue Bear"], Cat
|
37
|
+
store_names ["Red Bear"], Animal
|
38
|
+
assert_equal ["Green Bear", "Blue Bear"], Animal.search("bear", type: [Dog, Cat]).map(&:name)
|
39
|
+
end
|
40
|
+
|
28
41
|
def test_child_autocomplete
|
29
42
|
store_names ["Max"], Cat
|
30
43
|
store_names ["Mark"], Dog
|
data/test/sql_test.rb
CHANGED
@@ -60,6 +60,7 @@ class TestSql < Minitest::Unit::TestCase
|
|
60
60
|
assert_search "product", ["Product A", "Product B"], where: {store_id: [1, 2]}
|
61
61
|
assert_search "product", ["Product B", "Product C", "Product D"], where: {store_id: {not: 1}}
|
62
62
|
assert_search "product", ["Product C", "Product D"], where: {store_id: {not: [1, 2]}}
|
63
|
+
assert_search "product", ["Product A"], where: {user_ids: {lte: 2, gte: 2}}
|
63
64
|
# or
|
64
65
|
assert_search "product", ["Product A", "Product B", "Product C"], where: {or: [[{in_stock: true}, {store_id: 3}]]}
|
65
66
|
assert_search "product", ["Product A", "Product B", "Product C"], where: {or: [[{orders_count: [2, 4]}, {store_id: [1, 2]}]]}
|
@@ -105,6 +106,25 @@ class TestSql < Minitest::Unit::TestCase
|
|
105
106
|
assert_search "product", [], where: {store_id: []}
|
106
107
|
end
|
107
108
|
|
109
|
+
# http://elasticsearch-users.115913.n3.nabble.com/Numeric-range-quey-or-filter-in-an-array-field-possible-or-not-td4042967.html
|
110
|
+
# https://gist.github.com/jprante/7099463
|
111
|
+
def test_where_range_array
|
112
|
+
store [
|
113
|
+
{name: "Product A", user_ids: [11, 23, 13, 16, 17, 23.6]},
|
114
|
+
{name: "Product B", user_ids: [1, 2, 3, 4, 5, 6, 7, 8, 8.9, 9.1, 9.4]},
|
115
|
+
{name: "Product C", user_ids: [101, 230, 150, 200]}
|
116
|
+
]
|
117
|
+
assert_search "product", ["Product A"], where: {user_ids: {gt: 10, lt: 23.9}}
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_where_range_array_again
|
121
|
+
store [
|
122
|
+
{name: "Product A", user_ids: [19, 32, 42]},
|
123
|
+
{name: "Product B", user_ids: [13, 40, 52]}
|
124
|
+
]
|
125
|
+
assert_search "product", ["Product A"], where: {user_ids: {gt: 26, lt: 36}}
|
126
|
+
end
|
127
|
+
|
108
128
|
def test_near
|
109
129
|
store [
|
110
130
|
{name: "San Francisco", latitude: 37.7833, longitude: -122.4167},
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: searchkick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tire
|