searchkick 0.4.1 → 0.4.2
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 +6 -0
- data/README.md +46 -1
- data/lib/searchkick/model.rb +27 -11
- data/lib/searchkick/reindex.rb +151 -146
- data/lib/searchkick/search.rb +10 -2
- data/lib/searchkick/version.rb +1 -1
- data/lib/searchkick.rb +16 -0
- data/test/index_test.rb +6 -0
- data/test/inheritance_test.rb +0 -5
- data/test/model_test.rb +35 -0
- data/test/should_index_test.rb +34 -0
- data/test/test_helper.rb +25 -6
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93348e8748debeefc0be073340665c5024b961af
|
4
|
+
data.tar.gz: a4c73f4e8147ba2120d7e3388205fa056128d392
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f75f44631fee7348ff9aaf3d24f99b1954d5cef1868cc17f73c44c1dc17918f6eaa158dd35c46a582b31ec7d226384782421cd3c15f33b5a5e1b1f426266d90
|
7
|
+
data.tar.gz: 6be3ea5ed0ac0002b4628ad3cc067c0352b4724b9318836e2affe2c05c167132113e00b1ea8515f9e806054a57e3d7cb98a6f3c904f549885960fad72caa4e98
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -72,6 +72,8 @@ Query like SQL
|
|
72
72
|
Product.search "2% Milk", where: {in_stock: true}, limit: 10, offset: 50
|
73
73
|
```
|
74
74
|
|
75
|
+
**Note:** If you prefer the Elasticsearch DSL, see the [Advanced section](#advanced)
|
76
|
+
|
75
77
|
Search specific fields
|
76
78
|
|
77
79
|
```ruby
|
@@ -195,6 +197,16 @@ class Product < ActiveRecord::Base
|
|
195
197
|
end
|
196
198
|
```
|
197
199
|
|
200
|
+
By default, all records are indexed. To control which records are indexed, use the `should_index?` method.
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
class Product < ActiveRecord::Base
|
204
|
+
def should_index?
|
205
|
+
active # only index active records
|
206
|
+
end
|
207
|
+
end
|
208
|
+
```
|
209
|
+
|
198
210
|
### To Reindex, or Not to Reindex
|
199
211
|
|
200
212
|
#### Reindex
|
@@ -494,6 +506,30 @@ Then deploy and reindex:
|
|
494
506
|
rake searchkick:reindex CLASS=Product
|
495
507
|
```
|
496
508
|
|
509
|
+
## Advanced
|
510
|
+
|
511
|
+
Prefer to use the [Elasticsearch DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-queries.html) but still want awesome features like zero-downtime reindexing?
|
512
|
+
|
513
|
+
Create a custom mapping:
|
514
|
+
|
515
|
+
```ruby
|
516
|
+
class Product < ActiveRecord::Base
|
517
|
+
searchkick mappings: {
|
518
|
+
product: {
|
519
|
+
properties: {
|
520
|
+
name: {type: "string", analyzer: "keyword"}
|
521
|
+
}
|
522
|
+
}
|
523
|
+
}
|
524
|
+
end
|
525
|
+
```
|
526
|
+
|
527
|
+
And use the `query` option to search:
|
528
|
+
|
529
|
+
```ruby
|
530
|
+
Product.search query: {match: {name: "milk"}}
|
531
|
+
```
|
532
|
+
|
497
533
|
## Reference
|
498
534
|
|
499
535
|
Searchkick requires Elasticsearch `0.90.0` or higher.
|
@@ -527,7 +563,7 @@ class Product < ActiveRecord::Base
|
|
527
563
|
end
|
528
564
|
```
|
529
565
|
|
530
|
-
Turn off callbacks
|
566
|
+
Turn off callbacks permanently
|
531
567
|
|
532
568
|
```ruby
|
533
569
|
class Product < ActiveRecord::Base
|
@@ -535,6 +571,15 @@ class Product < ActiveRecord::Base
|
|
535
571
|
end
|
536
572
|
```
|
537
573
|
|
574
|
+
or temporarily
|
575
|
+
|
576
|
+
```ruby
|
577
|
+
Product.disable_search_callbacks # use Searchkick.disable_callbacks for all models
|
578
|
+
ExpensiveProductsTask.execute
|
579
|
+
Product.enable_search_callbacks
|
580
|
+
Product.reindex
|
581
|
+
```
|
582
|
+
|
538
583
|
Eager load associations
|
539
584
|
|
540
585
|
```ruby
|
data/lib/searchkick/model.rb
CHANGED
@@ -8,6 +8,7 @@ module Searchkick
|
|
8
8
|
class_variable_set :@@searchkick_options, options.dup
|
9
9
|
class_variable_set :@@searchkick_env, ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
|
10
10
|
class_variable_set :@@searchkick_klass, self
|
11
|
+
class_variable_set :@@searchkick_callbacks, options[:callbacks] != false
|
11
12
|
|
12
13
|
# set index name
|
13
14
|
# TODO support proc
|
@@ -18,19 +19,34 @@ module Searchkick
|
|
18
19
|
extend Searchkick::Reindex
|
19
20
|
include Searchkick::Similar
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
after_save :reindex
|
23
|
+
after_destroy :reindex
|
24
|
+
|
25
|
+
def self.enable_search_callbacks
|
26
|
+
class_variable_set :@@searchkick_callbacks, true
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.disable_search_callbacks
|
30
|
+
class_variable_set :@@searchkick_callbacks, false
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.search_callbacks?
|
34
|
+
class_variable_get(:@@searchkick_callbacks) && Searchkick.callbacks?
|
35
|
+
end
|
36
|
+
|
37
|
+
def should_index?
|
38
|
+
true
|
28
39
|
end
|
29
40
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
41
|
+
def reindex
|
42
|
+
if self.class.search_callbacks?
|
43
|
+
index = self.class.searchkick_index
|
44
|
+
if destroyed? or !should_index?
|
45
|
+
index.remove self
|
46
|
+
else
|
47
|
+
index.store self
|
48
|
+
end
|
49
|
+
end
|
34
50
|
end
|
35
51
|
|
36
52
|
def search_data
|
data/lib/searchkick/reindex.rb
CHANGED
@@ -62,14 +62,14 @@ module Searchkick
|
|
62
62
|
scope = scope.search_import if scope.respond_to?(:search_import)
|
63
63
|
if scope.respond_to?(:find_in_batches)
|
64
64
|
scope.find_in_batches do |batch|
|
65
|
-
index.import batch
|
65
|
+
index.import batch.select{|item| item.should_index? }
|
66
66
|
end
|
67
67
|
else
|
68
68
|
# https://github.com/karmi/tire/blob/master/lib/tire/model/import.rb
|
69
69
|
# use cursor for Mongoid
|
70
70
|
items = []
|
71
71
|
scope.all.each do |item|
|
72
|
-
items << item
|
72
|
+
items << item if item.should_index?
|
73
73
|
if items.length % 1000 == 0
|
74
74
|
index.import items
|
75
75
|
items = []
|
@@ -82,174 +82,179 @@ module Searchkick
|
|
82
82
|
def searchkick_index_options
|
83
83
|
options = searchkick_options
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
token_separator: ""
|
85
|
+
if options[:mappings]
|
86
|
+
settings = options[:settings] || {}
|
87
|
+
mappings = options[:mappings]
|
88
|
+
else
|
89
|
+
settings = {
|
90
|
+
analysis: {
|
91
|
+
analyzer: {
|
92
|
+
searchkick_keyword: {
|
93
|
+
type: "custom",
|
94
|
+
tokenizer: "keyword",
|
95
|
+
filter: ["lowercase", "snowball"]
|
96
|
+
},
|
97
|
+
default_index: {
|
98
|
+
type: "custom",
|
99
|
+
tokenizer: "standard",
|
100
|
+
# synonym should come last, after stemming and shingle
|
101
|
+
# shingle must come before snowball
|
102
|
+
filter: ["standard", "lowercase", "asciifolding", "stop", "searchkick_index_shingle", "snowball"]
|
103
|
+
},
|
104
|
+
searchkick_search: {
|
105
|
+
type: "custom",
|
106
|
+
tokenizer: "standard",
|
107
|
+
filter: ["standard", "lowercase", "asciifolding", "stop", "searchkick_search_shingle", "snowball"]
|
108
|
+
},
|
109
|
+
searchkick_search2: {
|
110
|
+
type: "custom",
|
111
|
+
tokenizer: "standard",
|
112
|
+
filter: ["standard", "lowercase", "asciifolding", "stop", "snowball"]
|
113
|
+
},
|
114
|
+
# https://github.com/leschenko/elasticsearch_autocomplete/blob/master/lib/elasticsearch_autocomplete/analyzers.rb
|
115
|
+
searchkick_autocomplete_index: {
|
116
|
+
type: "custom",
|
117
|
+
tokenizer: "searchkick_autocomplete_ngram",
|
118
|
+
filter: ["lowercase", "asciifolding"]
|
119
|
+
},
|
120
|
+
searchkick_autocomplete_search: {
|
121
|
+
type: "custom",
|
122
|
+
tokenizer: "keyword",
|
123
|
+
filter: ["lowercase", "asciifolding"]
|
124
|
+
},
|
125
|
+
searchkick_suggest_index: {
|
126
|
+
type: "custom",
|
127
|
+
tokenizer: "standard",
|
128
|
+
filter: ["lowercase", "asciifolding", "searchkick_suggest_shingle"]
|
129
|
+
}
|
131
130
|
},
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
131
|
+
filter: {
|
132
|
+
searchkick_index_shingle: {
|
133
|
+
type: "shingle",
|
134
|
+
token_separator: ""
|
135
|
+
},
|
136
|
+
# lucky find http://web.archiveorange.com/archive/v/AAfXfQ17f57FcRINsof7
|
137
|
+
searchkick_search_shingle: {
|
138
|
+
type: "shingle",
|
139
|
+
token_separator: "",
|
140
|
+
output_unigrams: false,
|
141
|
+
output_unigrams_if_no_shingles: true
|
142
|
+
},
|
143
|
+
searchkick_suggest_shingle: {
|
144
|
+
type: "shingle",
|
145
|
+
max_shingle_size: 5
|
146
|
+
}
|
138
147
|
},
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
searchkick_autocomplete_ngram: {
|
146
|
-
type: "edgeNGram",
|
147
|
-
min_gram: 1,
|
148
|
-
max_gram: 50
|
148
|
+
tokenizer: {
|
149
|
+
searchkick_autocomplete_ngram: {
|
150
|
+
type: "edgeNGram",
|
151
|
+
min_gram: 1,
|
152
|
+
max_gram: 50
|
153
|
+
}
|
149
154
|
}
|
150
155
|
}
|
151
156
|
}
|
152
|
-
}
|
153
157
|
|
154
|
-
|
155
|
-
|
156
|
-
|
158
|
+
if searchkick_env == "test"
|
159
|
+
settings.merge!(number_of_shards: 1, number_of_replicas: 0)
|
160
|
+
end
|
157
161
|
|
158
|
-
|
162
|
+
settings.merge!(options[:settings] || {})
|
159
163
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
164
|
+
# synonyms
|
165
|
+
synonyms = options[:synonyms] || []
|
166
|
+
if synonyms.any?
|
167
|
+
settings[:analysis][:filter][:searchkick_synonym] = {
|
168
|
+
type: "synonym",
|
169
|
+
synonyms: synonyms.select{|s| s.size > 1 }.map{|s| s.join(",") }
|
170
|
+
}
|
171
|
+
# choosing a place for the synonym filter when stemming is not easy
|
172
|
+
# https://groups.google.com/forum/#!topic/elasticsearch/p7qcQlgHdB8
|
173
|
+
# TODO use a snowball stemmer on synonyms when creating the token filter
|
170
174
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
175
|
+
# http://elasticsearch-users.115913.n3.nabble.com/synonym-multi-words-search-td4030811.html
|
176
|
+
# I find the following approach effective if you are doing multi-word synonyms (synonym phrases):
|
177
|
+
# - Only apply the synonym expansion at index time
|
178
|
+
# - Don't have the synonym filter applied search
|
179
|
+
# - Use directional synonyms where appropriate. You want to make sure that you're not injecting terms that are too general.
|
180
|
+
settings[:analysis][:analyzer][:default_index][:filter].insert(4, "searchkick_synonym")
|
181
|
+
settings[:analysis][:analyzer][:default_index][:filter] << "searchkick_synonym"
|
182
|
+
end
|
179
183
|
|
180
|
-
|
181
|
-
|
182
|
-
|
184
|
+
if options[:special_characters] == false
|
185
|
+
settings[:analysis][:analyzer].each do |analyzer, analyzer_settings|
|
186
|
+
analyzer_settings[:filter].reject!{|f| f == "asciifolding" }
|
187
|
+
end
|
183
188
|
end
|
184
|
-
end
|
185
189
|
|
186
|
-
|
190
|
+
mapping = {}
|
187
191
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
192
|
+
# conversions
|
193
|
+
if options[:conversions]
|
194
|
+
mapping[:conversions] = {
|
195
|
+
type: "nested",
|
196
|
+
properties: {
|
197
|
+
query: {type: "string", analyzer: "searchkick_keyword"},
|
198
|
+
count: {type: "integer"}
|
199
|
+
}
|
195
200
|
}
|
196
|
-
|
197
|
-
end
|
201
|
+
end
|
198
202
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
203
|
+
# autocomplete and suggest
|
204
|
+
autocomplete = (options[:autocomplete] || []).map(&:to_s)
|
205
|
+
suggest = (options[:suggest] || []).map(&:to_s)
|
206
|
+
(autocomplete + suggest).uniq.each do |field|
|
207
|
+
field_mapping = {
|
208
|
+
type: "multi_field",
|
209
|
+
fields: {
|
210
|
+
field => {type: "string", index: "not_analyzed"},
|
211
|
+
"analyzed" => {type: "string", index: "analyzed"}
|
212
|
+
# term_vector: "with_positions_offsets" for fast / correct highlighting
|
213
|
+
# http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html#_fast_vector_highlighter
|
214
|
+
}
|
210
215
|
}
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
216
|
+
if autocomplete.include?(field)
|
217
|
+
field_mapping[:fields]["autocomplete"] = {type: "string", index: "analyzed", analyzer: "searchkick_autocomplete_index"}
|
218
|
+
end
|
219
|
+
if suggest.include?(field)
|
220
|
+
field_mapping[:fields]["suggest"] = {type: "string", index: "analyzed", analyzer: "searchkick_suggest_index"}
|
221
|
+
end
|
222
|
+
mapping[field] = field_mapping
|
217
223
|
end
|
218
|
-
mapping[field] = field_mapping
|
219
|
-
end
|
220
224
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
225
|
+
(options[:locations] || []).each do |field|
|
226
|
+
mapping[field] = {
|
227
|
+
type: "geo_point"
|
228
|
+
}
|
229
|
+
end
|
226
230
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
# http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
|
238
|
-
type: "multi_field",
|
239
|
-
fields: {
|
240
|
-
# analyzed field must be the default field for include_in_all
|
231
|
+
mappings = {
|
232
|
+
_default_: {
|
233
|
+
properties: mapping,
|
234
|
+
# https://gist.github.com/kimchy/2898285
|
235
|
+
dynamic_templates: [
|
236
|
+
{
|
237
|
+
string_template: {
|
238
|
+
match: "*",
|
239
|
+
match_mapping_type: "string",
|
240
|
+
mapping: {
|
241
241
|
# http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
242
|
+
type: "multi_field",
|
243
|
+
fields: {
|
244
|
+
# analyzed field must be the default field for include_in_all
|
245
|
+
# http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
|
246
|
+
# however, we can include the not_analyzed field in _all
|
247
|
+
# and the _all index analyzer will take care of it
|
248
|
+
"{name}" => {type: "string", index: "not_analyzed"},
|
249
|
+
"analyzed" => {type: "string", index: "analyzed"}
|
250
|
+
}
|
246
251
|
}
|
247
252
|
}
|
248
253
|
}
|
249
|
-
|
250
|
-
|
254
|
+
]
|
255
|
+
}
|
251
256
|
}
|
252
|
-
|
257
|
+
end
|
253
258
|
|
254
259
|
{
|
255
260
|
settings: settings,
|
data/lib/searchkick/search.rb
CHANGED
@@ -2,7 +2,13 @@ module Searchkick
|
|
2
2
|
module Search
|
3
3
|
|
4
4
|
def search(term, options = {})
|
5
|
-
|
5
|
+
if term.is_a?(Hash)
|
6
|
+
options = term
|
7
|
+
term = nil
|
8
|
+
else
|
9
|
+
term = term.to_s
|
10
|
+
end
|
11
|
+
|
6
12
|
fields =
|
7
13
|
if options[:fields]
|
8
14
|
if options[:autocomplete]
|
@@ -35,7 +41,9 @@ module Searchkick
|
|
35
41
|
|
36
42
|
all = term == "*"
|
37
43
|
|
38
|
-
if options[:
|
44
|
+
if options[:query]
|
45
|
+
payload = options[:query]
|
46
|
+
elsif options[:similar]
|
39
47
|
payload = {
|
40
48
|
more_like_this: {
|
41
49
|
fields: fields,
|
data/lib/searchkick/version.rb
CHANGED
data/lib/searchkick.rb
CHANGED
@@ -8,6 +8,22 @@ require "searchkick/model"
|
|
8
8
|
require "searchkick/tasks"
|
9
9
|
require "searchkick/logger" if defined?(Rails)
|
10
10
|
|
11
|
+
module Searchkick
|
12
|
+
@callbacks = true
|
13
|
+
|
14
|
+
def self.enable_callbacks
|
15
|
+
@callbacks = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.disable_callbacks
|
19
|
+
@callbacks = false
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.callbacks?
|
23
|
+
@callbacks
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
11
27
|
# TODO find better ActiveModel hook
|
12
28
|
ActiveModel::Callbacks.send(:include, Searchkick::Model)
|
13
29
|
ActiveRecord::Base.send(:extend, Searchkick::Model) if defined?(ActiveRecord)
|
data/test/index_test.rb
CHANGED
@@ -26,4 +26,10 @@ class TestIndex < Minitest::Unit::TestCase
|
|
26
26
|
assert !old_index.exists?
|
27
27
|
end
|
28
28
|
|
29
|
+
def test_mapping
|
30
|
+
store_names ["Dollar Tree"], Store
|
31
|
+
assert_equal [], Store.search(query: {match: {name: "dollar"}}).map(&:name)
|
32
|
+
assert_equal ["Dollar Tree"], Store.search(query: {match: {name: "Dollar Tree"}}).map(&:name)
|
33
|
+
end
|
34
|
+
|
29
35
|
end
|
data/test/inheritance_test.rb
CHANGED
data/test/model_test.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
class TestModel < Minitest::Unit::TestCase
|
4
|
+
|
5
|
+
def test_disable_callbacks_model
|
6
|
+
store_names ["product a"]
|
7
|
+
|
8
|
+
Product.disable_search_callbacks
|
9
|
+
assert !Product.search_callbacks?
|
10
|
+
|
11
|
+
store_names ["product b"]
|
12
|
+
assert_search "product", ["product a"]
|
13
|
+
|
14
|
+
Product.enable_search_callbacks
|
15
|
+
Product.reindex
|
16
|
+
|
17
|
+
assert_search "product", ["product a", "product b"]
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_disable_callbacks_global
|
21
|
+
store_names ["product a"]
|
22
|
+
|
23
|
+
Searchkick.disable_callbacks
|
24
|
+
assert !Searchkick.callbacks?
|
25
|
+
|
26
|
+
store_names ["product b"]
|
27
|
+
assert_search "product", ["product a"]
|
28
|
+
|
29
|
+
Searchkick.enable_callbacks
|
30
|
+
Product.reindex
|
31
|
+
|
32
|
+
assert_search "product", ["product a", "product b"]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
|
3
|
+
class TestShouldIndex < Minitest::Unit::TestCase
|
4
|
+
|
5
|
+
def test_basic
|
6
|
+
store_names ["INDEX", "DO NOT INDEX"]
|
7
|
+
assert_search "index", ["INDEX"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_default_true
|
11
|
+
assert Animal.new.should_index?
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_change_to_true
|
15
|
+
store_names ["DO NOT INDEX"]
|
16
|
+
assert_search "index", []
|
17
|
+
product = Product.first
|
18
|
+
product.name = "INDEX"
|
19
|
+
product.save!
|
20
|
+
Product.searchkick_index.refresh
|
21
|
+
assert_search "index", ["INDEX"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_change_to_false
|
25
|
+
store_names ["INDEX"]
|
26
|
+
assert_search "index", ["INDEX"]
|
27
|
+
product = Product.first
|
28
|
+
product.name = "DO NOT INDEX"
|
29
|
+
product.save!
|
30
|
+
Product.searchkick_index.refresh
|
31
|
+
assert_search "index", []
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -33,6 +33,8 @@ if defined?(Mongoid)
|
|
33
33
|
|
34
34
|
class Store
|
35
35
|
include Mongoid::Document
|
36
|
+
|
37
|
+
field :name
|
36
38
|
end
|
37
39
|
|
38
40
|
class Animal
|
@@ -73,6 +75,7 @@ else
|
|
73
75
|
end
|
74
76
|
|
75
77
|
ActiveRecord::Migration.create_table :stores, :force => true do |t|
|
78
|
+
t.string :name
|
76
79
|
end
|
77
80
|
|
78
81
|
ActiveRecord::Migration.create_table :animals, :force => true do |t|
|
@@ -119,6 +122,20 @@ class Product
|
|
119
122
|
def search_data
|
120
123
|
serializable_hash.merge conversions: conversions, user_ids: user_ids, location: [latitude, longitude], multiple_locations: [[latitude, longitude], [0, 0]]
|
121
124
|
end
|
125
|
+
|
126
|
+
def should_index?
|
127
|
+
name != "DO NOT INDEX"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class Store
|
132
|
+
searchkick mappings: {
|
133
|
+
store: {
|
134
|
+
properties: {
|
135
|
+
name: {type: "string", analyzer: "keyword"}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
122
139
|
end
|
123
140
|
|
124
141
|
class Animal
|
@@ -129,12 +146,14 @@ Product.searchkick_index.delete if Product.searchkick_index.exists?
|
|
129
146
|
Product.reindex
|
130
147
|
Product.reindex # run twice for both index paths
|
131
148
|
|
149
|
+
Store.reindex
|
132
150
|
Animal.reindex
|
133
151
|
|
134
152
|
class Minitest::Unit::TestCase
|
135
153
|
|
136
154
|
def setup
|
137
155
|
Product.destroy_all
|
156
|
+
Animal.destroy_all
|
138
157
|
end
|
139
158
|
|
140
159
|
protected
|
@@ -151,16 +170,16 @@ class Minitest::Unit::TestCase
|
|
151
170
|
end
|
152
171
|
|
153
172
|
# no order
|
154
|
-
def assert_search(term, expected, options = {})
|
155
|
-
assert_equal expected.sort,
|
173
|
+
def assert_search(term, expected, options = {}, klass = Product)
|
174
|
+
assert_equal expected.sort, klass.search(term, options).map(&:name).sort
|
156
175
|
end
|
157
176
|
|
158
|
-
def assert_order(term, expected, options = {})
|
159
|
-
assert_equal expected,
|
177
|
+
def assert_order(term, expected, options = {}, klass = Product)
|
178
|
+
assert_equal expected, klass.search(term, options).map(&:name)
|
160
179
|
end
|
161
180
|
|
162
|
-
def assert_first(term, expected, options = {})
|
163
|
-
assert_equal expected,
|
181
|
+
def assert_first(term, expected, options = {}, klass = Product)
|
182
|
+
assert_equal expected, klass.search(term, options).map(&:name).first
|
164
183
|
end
|
165
184
|
|
166
185
|
end
|
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.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-12-
|
11
|
+
date: 2013-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tire
|
@@ -141,6 +141,8 @@ files:
|
|
141
141
|
- test/index_test.rb
|
142
142
|
- test/inheritance_test.rb
|
143
143
|
- test/match_test.rb
|
144
|
+
- test/model_test.rb
|
145
|
+
- test/should_index_test.rb
|
144
146
|
- test/similar_test.rb
|
145
147
|
- test/sql_test.rb
|
146
148
|
- test/suggest_test.rb
|
@@ -178,6 +180,8 @@ test_files:
|
|
178
180
|
- test/index_test.rb
|
179
181
|
- test/inheritance_test.rb
|
180
182
|
- test/match_test.rb
|
183
|
+
- test/model_test.rb
|
184
|
+
- test/should_index_test.rb
|
181
185
|
- test/similar_test.rb
|
182
186
|
- test/sql_test.rb
|
183
187
|
- test/suggest_test.rb
|