searchkick 0.5.0 → 0.5.1
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 +8 -0
- data/README.md +50 -7
- data/lib/searchkick/model.rb +10 -10
- data/lib/searchkick/reindex.rb +9 -5
- data/lib/searchkick/search.rb +8 -3
- data/lib/searchkick/version.rb +1 -1
- data/test/match_test.rb +5 -0
- data/test/sql_test.rb +26 -0
- data/test/test_helper.rb +2 -1
- 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: c2afa6ea99c2995b003f51cbe409392097fdfa8e
|
4
|
+
data.tar.gz: dc2e4add51195454636f94db1ae6417c2a8933bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1895d905c2b916de3e5e5fb5640d8132318f0dccffa553cfd6770d1c38d84bcd5dc9c92d1749711fa16f0bfdf677962318a5ec50e366f91e0dd1324121bf169f
|
7
|
+
data.tar.gz: 8c9bc21cf09a320ee676d2307f7ebbdbf1cc2f2dce37633e799f6282ee2f3f1d8e5ba0af1696c23c2271f401ca1173b4803779f6f50f43cd8674db15c7483620
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 0.5.1
|
2
|
+
|
3
|
+
- Replaced stop words with common terms query
|
4
|
+
- Added language option
|
5
|
+
- Fixed bug with empty array in where clause
|
6
|
+
- Fixed bug with MongoDB integer _id
|
7
|
+
- Fixed reindex bug when callbacks disabled
|
8
|
+
|
1
9
|
## 0.5.0
|
2
10
|
|
3
11
|
- Better control over partial matches
|
data/README.md
CHANGED
@@ -21,12 +21,14 @@ Plus:
|
|
21
21
|
- “Did you mean” suggestions
|
22
22
|
- works with ActiveRecord and Mongoid
|
23
23
|
|
24
|
-
:zap: Even better with [Searchjoy](http://ankane.github.io/searchjoy/)
|
25
|
-
|
26
24
|
:tangerine: Battle-tested at [Instacart](https://www.instacart.com)
|
27
25
|
|
28
26
|
[](https://travis-ci.org/ankane/searchkick)
|
29
27
|
|
28
|
+
We highly recommend tracking queries and conversions
|
29
|
+
|
30
|
+
:zap: [Searchjoy](http://ankane.github.io/searchjoy/) makes it easy
|
31
|
+
|
30
32
|
## Get Started
|
31
33
|
|
32
34
|
[Install Elasticsearch](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/setup.html). For Homebrew, use:
|
@@ -174,6 +176,18 @@ Available options are:
|
|
174
176
|
:text_end
|
175
177
|
```
|
176
178
|
|
179
|
+
### Language
|
180
|
+
|
181
|
+
Searchkick defaults to English for stemming. To change this, use:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
class Product < ActiveRecord::Base
|
185
|
+
searchkick language: "German"
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
[See the list of languages](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis-snowball-tokenfilter.html)
|
190
|
+
|
177
191
|
### Synonyms
|
178
192
|
|
179
193
|
```ruby
|
@@ -219,7 +233,7 @@ Searchkick uses `find_in_batches` to import documents. To eager load associatio
|
|
219
233
|
|
220
234
|
```ruby
|
221
235
|
class Product < ActiveRecord::Base
|
222
|
-
scope :search_import, includes(:searches)
|
236
|
+
scope :search_import, -> { includes(:searches) }
|
223
237
|
end
|
224
238
|
```
|
225
239
|
|
@@ -556,7 +570,7 @@ And use the `query` option to search:
|
|
556
570
|
Product.search query: {match: {name: "milk"}}
|
557
571
|
```
|
558
572
|
|
559
|
-
|
573
|
+
To keep the mappings and settings generated by Searchkick, use:
|
560
574
|
|
561
575
|
```ruby
|
562
576
|
class Product < ActiveRecord::Base
|
@@ -608,9 +622,9 @@ end
|
|
608
622
|
or temporarily
|
609
623
|
|
610
624
|
```ruby
|
611
|
-
Product.disable_search_callbacks # use Searchkick.disable_callbacks for all models
|
625
|
+
Product.disable_search_callbacks # or use Searchkick.disable_callbacks for all models
|
612
626
|
ExpensiveProductsTask.execute
|
613
|
-
Product.enable_search_callbacks
|
627
|
+
Product.enable_search_callbacks # or use Searchkick.enable_callbacks for all models
|
614
628
|
Product.reindex
|
615
629
|
```
|
616
630
|
|
@@ -635,7 +649,7 @@ class Product < ActiveRecord::Base
|
|
635
649
|
end
|
636
650
|
```
|
637
651
|
|
638
|
-
Change import batch size
|
652
|
+
Change import batch size
|
639
653
|
|
640
654
|
```ruby
|
641
655
|
class Product < ActiveRecord::Base
|
@@ -643,6 +657,35 @@ class Product < ActiveRecord::Base
|
|
643
657
|
end
|
644
658
|
```
|
645
659
|
|
660
|
+
Reindex conditionally
|
661
|
+
|
662
|
+
```ruby
|
663
|
+
class Product < ActiveRecord::Base
|
664
|
+
searchkick callbacks: false
|
665
|
+
|
666
|
+
# add the callbacks manually
|
667
|
+
after_save :reindex, if: proc{|model| model.name_changed? } # use your own condition
|
668
|
+
after_destroy :reindex
|
669
|
+
end
|
670
|
+
```
|
671
|
+
|
672
|
+
Asynchronous reindexing
|
673
|
+
|
674
|
+
```ruby
|
675
|
+
class Product < ActiveRecord::Base
|
676
|
+
searchkick callbacks: false
|
677
|
+
|
678
|
+
# add the callbacks manually
|
679
|
+
after_save :reindex_async
|
680
|
+
after_destroy :reindex_async
|
681
|
+
|
682
|
+
def reindex_async
|
683
|
+
# delayed job
|
684
|
+
delay.reindex
|
685
|
+
end
|
686
|
+
end
|
687
|
+
```
|
688
|
+
|
646
689
|
Reindex all models (Rails only)
|
647
690
|
|
648
691
|
```sh
|
data/lib/searchkick/model.rb
CHANGED
@@ -19,8 +19,8 @@ module Searchkick
|
|
19
19
|
extend Searchkick::Reindex
|
20
20
|
include Searchkick::Similar
|
21
21
|
|
22
|
-
after_save :reindex
|
23
|
-
after_destroy :reindex
|
22
|
+
after_save :reindex, if: proc { self.class.search_callbacks? }
|
23
|
+
after_destroy :reindex, if: proc { self.class.search_callbacks? }
|
24
24
|
|
25
25
|
def self.enable_search_callbacks
|
26
26
|
class_variable_set :@@searchkick_callbacks, true
|
@@ -39,13 +39,11 @@ module Searchkick
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def reindex
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
index.store self
|
48
|
-
end
|
42
|
+
index = self.class.searchkick_index
|
43
|
+
if destroyed? or !should_index?
|
44
|
+
index.remove self
|
45
|
+
else
|
46
|
+
index.store self
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -60,7 +58,9 @@ module Searchkick
|
|
60
58
|
source = source.inject({}){|memo,(k,v)| memo[k.to_s] = v; memo}
|
61
59
|
|
62
60
|
# Mongoid 4 hack
|
63
|
-
|
61
|
+
if defined?(BSON::ObjectId) and source["_id"].is_a?(BSON::ObjectId)
|
62
|
+
source["_id"] = source["_id"].to_s
|
63
|
+
end
|
64
64
|
|
65
65
|
options = self.class.searchkick_options
|
66
66
|
|
data/lib/searchkick/reindex.rb
CHANGED
@@ -94,24 +94,24 @@ module Searchkick
|
|
94
94
|
searchkick_keyword: {
|
95
95
|
type: "custom",
|
96
96
|
tokenizer: "keyword",
|
97
|
-
filter: ["lowercase", "
|
97
|
+
filter: ["lowercase", "searchkick_stemmer"]
|
98
98
|
},
|
99
99
|
default_index: {
|
100
100
|
type: "custom",
|
101
101
|
tokenizer: "standard",
|
102
102
|
# synonym should come last, after stemming and shingle
|
103
|
-
# shingle must come before
|
104
|
-
filter: ["standard", "lowercase", "asciifolding", "
|
103
|
+
# shingle must come before searchkick_stemmer
|
104
|
+
filter: ["standard", "lowercase", "asciifolding", "searchkick_index_shingle", "searchkick_stemmer"]
|
105
105
|
},
|
106
106
|
searchkick_search: {
|
107
107
|
type: "custom",
|
108
108
|
tokenizer: "standard",
|
109
|
-
filter: ["standard", "lowercase", "asciifolding", "
|
109
|
+
filter: ["standard", "lowercase", "asciifolding", "searchkick_search_shingle", "searchkick_stemmer"]
|
110
110
|
},
|
111
111
|
searchkick_search2: {
|
112
112
|
type: "custom",
|
113
113
|
tokenizer: "standard",
|
114
|
-
filter: ["standard", "lowercase", "asciifolding", "
|
114
|
+
filter: ["standard", "lowercase", "asciifolding", "searchkick_stemmer"]
|
115
115
|
},
|
116
116
|
# https://github.com/leschenko/elasticsearch_autocomplete/blob/master/lib/elasticsearch_autocomplete/analyzers.rb
|
117
117
|
searchkick_autocomplete_index: {
|
@@ -190,6 +190,10 @@ module Searchkick
|
|
190
190
|
type: "nGram",
|
191
191
|
min_gram: 1,
|
192
192
|
max_gram: 50
|
193
|
+
},
|
194
|
+
searchkick_stemmer: {
|
195
|
+
type: "snowball",
|
196
|
+
language: options[:language] || "English"
|
193
197
|
}
|
194
198
|
},
|
195
199
|
tokenizer: {
|
data/lib/searchkick/search.rb
CHANGED
@@ -77,7 +77,8 @@ module Searchkick
|
|
77
77
|
fields: [field],
|
78
78
|
query: term,
|
79
79
|
use_dis_max: false,
|
80
|
-
operator: operator
|
80
|
+
operator: operator,
|
81
|
+
cutoff_frequency: 0.001
|
81
82
|
}
|
82
83
|
queries.concat [
|
83
84
|
{multi_match: shared_options.merge(boost: 10, analyzer: "searchkick_search")},
|
@@ -178,13 +179,17 @@ module Searchkick
|
|
178
179
|
# order
|
179
180
|
if options[:order]
|
180
181
|
order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc}
|
181
|
-
payload[:sort] = order
|
182
|
+
payload[:sort] = Hash[ order.map{|k, v| [k.to_s == "id" ? :_id : k, v] } ]
|
182
183
|
end
|
183
184
|
|
184
185
|
term_filters =
|
185
186
|
proc do |field, value|
|
186
187
|
if value.is_a?(Array) # in query
|
187
|
-
|
188
|
+
if value.any?
|
189
|
+
{or: value.map{|v| term_filters.call(field, v) }}
|
190
|
+
else
|
191
|
+
{terms: {field => value}} # match nothing
|
192
|
+
end
|
188
193
|
elsif value.nil?
|
189
194
|
{missing: {"field" => field, existence: true, null_value: true}}
|
190
195
|
else
|
data/lib/searchkick/version.rb
CHANGED
data/test/match_test.rb
CHANGED
data/test/sql_test.rb
CHANGED
@@ -95,6 +95,16 @@ class TestSql < Minitest::Unit::TestCase
|
|
95
95
|
assert_search "product", ["Product A"], where: {id: product.id.to_s}
|
96
96
|
end
|
97
97
|
|
98
|
+
def test_where_empty
|
99
|
+
store_names ["Product A"]
|
100
|
+
assert_search "product", ["Product A"], where: {}
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_where_empty_array
|
104
|
+
store_names ["Product A"]
|
105
|
+
assert_search "product", [], where: {store_id: []}
|
106
|
+
end
|
107
|
+
|
98
108
|
def test_near
|
99
109
|
store [
|
100
110
|
{name: "San Francisco", latitude: 37.7833, longitude: -122.4167},
|
@@ -138,6 +148,22 @@ class TestSql < Minitest::Unit::TestCase
|
|
138
148
|
assert_order "product", ["Product A", "Product B", "Product C", "Product D"], order: "name"
|
139
149
|
end
|
140
150
|
|
151
|
+
def test_order_id
|
152
|
+
store_names ["Product A", "Product B"]
|
153
|
+
product_a = Product.where(name: "Product A").first
|
154
|
+
product_b = Product.where(name: "Product B").first
|
155
|
+
assert_order "product", [product_a, product_b].sort_by(&:id).map(&:name), order: {id: :asc}
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_order_multiple
|
159
|
+
store [
|
160
|
+
{name: "Product A", color: "blue", store_id: 1},
|
161
|
+
{name: "Product B", color: "red", store_id: 3},
|
162
|
+
{name: "Product C", color: "red", store_id: 2}
|
163
|
+
]
|
164
|
+
assert_order "product", ["Product A", "Product B", "Product C"], order: {color: :asc, store_id: :desc}
|
165
|
+
end
|
166
|
+
|
141
167
|
def test_partial
|
142
168
|
store_names ["Honey"]
|
143
169
|
assert_search "fresh honey", []
|
data/test/test_helper.rb
CHANGED
@@ -126,7 +126,7 @@ class Product
|
|
126
126
|
attr_accessor :conversions, :user_ids
|
127
127
|
|
128
128
|
def search_data
|
129
|
-
serializable_hash.merge conversions: conversions, user_ids: user_ids, location: [latitude, longitude], multiple_locations: [[latitude, longitude], [0, 0]]
|
129
|
+
serializable_hash.except("id").merge conversions: conversions, user_ids: user_ids, location: [latitude, longitude], multiple_locations: [[latitude, longitude], [0, 0]]
|
130
130
|
end
|
131
131
|
|
132
132
|
def should_index?
|
@@ -159,6 +159,7 @@ class Minitest::Unit::TestCase
|
|
159
159
|
|
160
160
|
def setup
|
161
161
|
Product.destroy_all
|
162
|
+
Store.destroy_all
|
162
163
|
Animal.destroy_all
|
163
164
|
end
|
164
165
|
|
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.1
|
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-
|
11
|
+
date: 2014-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tire
|