searchkick 4.4.0 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -3
- data/README.md +233 -216
- data/lib/searchkick.rb +27 -11
- data/lib/searchkick/index.rb +11 -4
- data/lib/searchkick/index_options.rb +507 -396
- data/lib/searchkick/model.rb +1 -1
- data/lib/searchkick/query.rb +4 -4
- data/lib/searchkick/results.rb +102 -72
- data/lib/searchkick/version.rb +1 -1
- data/lib/tasks/searchkick.rake +12 -11
- metadata +7 -64
- data/CONTRIBUTING.md +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62e2797b9ad2290378febadeaab675b745b0318cd86a8219cada4774b529e290
|
4
|
+
data.tar.gz: 8f0956287e802ce93a67940f6283f914b58b38aee2240f3ef101ae08e7428966
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34a3bf2400766d7a2e95c3ba430a42c08dc1cfeb6c2d26b4d6d2a04828fd5ee296f3b121b076f00502f7c0c849ff27e1e622635a70885ef7f1336f0b4b8709de
|
7
|
+
data.tar.gz: 1c190e32fa87aa03a025a349dfc200ced4c28069c524acaa7b3c220628c58b9da2742ae4c924a87bc354f920a7486cae176d2bd7078a72a98568a068b20df290
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
## 4.5.0 (2021-06-07)
|
2
|
+
|
3
|
+
- Added experimental support for OpenSearch
|
4
|
+
- Added support for synonyms in Japanese
|
5
|
+
|
6
|
+
## 4.4.4 (2021-03-12)
|
7
|
+
|
8
|
+
- Fixed `too_long_frame_exception` with `scroll` method
|
9
|
+
- Fixed multi-word emoji tokenization
|
10
|
+
|
11
|
+
## 4.4.3 (2021-02-25)
|
12
|
+
|
13
|
+
- Added support for Hunspell
|
14
|
+
- Fixed warning about accessing system indices
|
15
|
+
|
16
|
+
## 4.4.2 (2020-11-23)
|
17
|
+
|
18
|
+
- Added `missing_records` method to results
|
19
|
+
- Fixed issue with `like` and special characters
|
20
|
+
|
21
|
+
## 4.4.1 (2020-06-24)
|
22
|
+
|
23
|
+
- Added `stem_exclusion` and `stemmer_override` options
|
24
|
+
- Added `with_score` method to search results
|
25
|
+
- Improved error message for `reload_synonyms` with non-OSS version of Elasticsearch
|
26
|
+
- Improved output for reindex rake task
|
27
|
+
|
1
28
|
## 4.4.0 (2020-06-17)
|
2
29
|
|
3
30
|
- Added support for reloadable, multi-word, search time synonyms
|
@@ -59,6 +86,7 @@ Breaking changes
|
|
59
86
|
|
60
87
|
- Removed support for Elasticsearch 5
|
61
88
|
- Removed support for multi-word synonyms (they no longer work with shingles)
|
89
|
+
- Removed support for Active Record < 5
|
62
90
|
|
63
91
|
## 3.1.3 (2019-04-11)
|
64
92
|
|
@@ -125,7 +153,7 @@ Breaking changes
|
|
125
153
|
Breaking changes
|
126
154
|
|
127
155
|
- Removed support for Elasticsearch 2
|
128
|
-
- Removed support for
|
156
|
+
- Removed support for Active Record < 4.2 and Mongoid < 5
|
129
157
|
- Types are no longer used
|
130
158
|
- The `_all` field is disabled by default in Elasticsearch 5
|
131
159
|
- Conversions are not stemmed by default
|
@@ -430,7 +458,7 @@ Breaking changes
|
|
430
458
|
|
431
459
|
## 0.8.3 (2014-09-20)
|
432
460
|
|
433
|
-
- Added support for
|
461
|
+
- Added support for Active Job
|
434
462
|
- Added `timeout` setting
|
435
463
|
- Fixed import with no records
|
436
464
|
|
@@ -537,7 +565,7 @@ Breaking changes
|
|
537
565
|
|
538
566
|
## 0.5.2 (2014-02-12)
|
539
567
|
|
540
|
-
- Use after_commit hook for
|
568
|
+
- Use after_commit hook for Active Record to prevent data inconsistencies
|
541
569
|
|
542
570
|
## 0.5.1 (2014-02-12)
|
543
571
|
|
data/README.md
CHANGED
@@ -22,24 +22,26 @@ Plus:
|
|
22
22
|
- supports many languages
|
23
23
|
- works with ActiveRecord, Mongoid, and NoBrainer
|
24
24
|
|
25
|
-
|
25
|
+
Check out [Searchjoy](https://github.com/ankane/searchjoy) for analytics and [Autosuggest](https://github.com/ankane/autosuggest) for query suggestions
|
26
26
|
|
27
|
-
:
|
27
|
+
:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
|
28
28
|
|
29
|
-
[![Build Status](https://
|
29
|
+
[![Build Status](https://github.com/ankane/searchkick/workflows/build/badge.svg?branch=master)](https://github.com/ankane/searchkick/actions)
|
30
30
|
|
31
31
|
## Contents
|
32
32
|
|
33
33
|
- [Getting Started](#getting-started)
|
34
34
|
- [Querying](#querying)
|
35
35
|
- [Indexing](#indexing)
|
36
|
+
- [Intelligent Search](#intelligent-search)
|
36
37
|
- [Instant Search / Autocomplete](#instant-search--autocomplete)
|
37
38
|
- [Aggregations](#aggregations)
|
39
|
+
- [Testing](#testing)
|
38
40
|
- [Deployment](#deployment)
|
39
41
|
- [Performance](#performance)
|
40
42
|
- [Elasticsearch DSL](#advanced)
|
41
43
|
- [Reference](#reference)
|
42
|
-
- [
|
44
|
+
- [Contributing](#contributing)
|
43
45
|
|
44
46
|
## Getting Started
|
45
47
|
|
@@ -174,7 +176,7 @@ Get the full response from Elasticsearch
|
|
174
176
|
results.response
|
175
177
|
```
|
176
178
|
|
177
|
-
**Note:** By default, Elasticsearch [limits paging](#deep-paging
|
179
|
+
**Note:** By default, Elasticsearch [limits paging](#deep-paging) to the first 10,000 results for performance. With Elasticsearch 7, this applies to the total count as well.
|
178
180
|
|
179
181
|
### Boosting
|
180
182
|
|
@@ -207,7 +209,7 @@ boost_by_recency: {created_at: {scale: "7d", decay: 0.5}}
|
|
207
209
|
|
208
210
|
You can also boost by:
|
209
211
|
|
210
|
-
- [Conversions](#
|
212
|
+
- [Conversions](#intelligent-search)
|
211
213
|
- [Distance](#boost-by-distance)
|
212
214
|
|
213
215
|
### Get Everything
|
@@ -297,7 +299,9 @@ To only match the exact order, use:
|
|
297
299
|
User.search "fresh honey", match: :phrase
|
298
300
|
```
|
299
301
|
|
300
|
-
### Language
|
302
|
+
### Stemming and Language
|
303
|
+
|
304
|
+
Searchkick stems words by default for better matching. `apple` and `apples` both stem to `appl`, so searches for either term will have the same matches.
|
301
305
|
|
302
306
|
Searchkick defaults to English for stemming. To change this, use:
|
303
307
|
|
@@ -307,9 +311,7 @@ class Product < ApplicationRecord
|
|
307
311
|
end
|
308
312
|
```
|
309
313
|
|
310
|
-
|
311
|
-
|
312
|
-
A few languages require plugins:
|
314
|
+
See the [list of languages](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-stemmer-tokenfilter.html#analysis-stemmer-tokenfilter-configure-parms). A few languages require plugins:
|
313
315
|
|
314
316
|
- `chinese` - [analysis-ik plugin](https://github.com/medcl/elasticsearch-analysis-ik)
|
315
317
|
- `chinese2` - [analysis-smartcn plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/7.4/analysis-smartcn.html)
|
@@ -320,6 +322,38 @@ A few languages require plugins:
|
|
320
322
|
- `ukrainian` - [analysis-ukrainian plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/7.4/analysis-ukrainian.html)
|
321
323
|
- `vietnamese` - [analysis-vietnamese plugin](https://github.com/duydo/elasticsearch-analysis-vietnamese)
|
322
324
|
|
325
|
+
You can also use a Hunspell dictionary for stemming.
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
class Product < ApplicationRecord
|
329
|
+
searchkick stemmer: {type: "hunspell", locale: "en_US"}
|
330
|
+
end
|
331
|
+
```
|
332
|
+
|
333
|
+
Disable stemming with:
|
334
|
+
|
335
|
+
```ruby
|
336
|
+
class Image < ApplicationRecord
|
337
|
+
searchkick stem: false
|
338
|
+
end
|
339
|
+
```
|
340
|
+
|
341
|
+
Exclude certain words from stemming with:
|
342
|
+
|
343
|
+
```ruby
|
344
|
+
class Image < ApplicationRecord
|
345
|
+
searchkick stem_exclusion: ["apples"]
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
349
|
+
Or change how words are stemmed:
|
350
|
+
|
351
|
+
```ruby
|
352
|
+
class Image < ApplicationRecord
|
353
|
+
searchkick stemmer_override: ["apples => other"]
|
354
|
+
end
|
355
|
+
```
|
356
|
+
|
323
357
|
### Synonyms
|
324
358
|
|
325
359
|
```ruby
|
@@ -333,7 +367,7 @@ Call `Product.reindex` after changing synonyms. Synonyms are applied at search t
|
|
333
367
|
For directional synonyms, use:
|
334
368
|
|
335
369
|
```ruby
|
336
|
-
|
370
|
+
search_synonyms: ["lightbulb => halogenlamp"]
|
337
371
|
```
|
338
372
|
|
339
373
|
### Dynamic Synonyms
|
@@ -358,7 +392,7 @@ search_synonyms: "synonyms.txt"
|
|
358
392
|
Add [elasticsearch-xpack](https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-xpack) to your Gemfile:
|
359
393
|
|
360
394
|
```ruby
|
361
|
-
gem 'elasticsearch-xpack', '>= 7.8.0
|
395
|
+
gem 'elasticsearch-xpack', '>= 7.8.0'
|
362
396
|
```
|
363
397
|
|
364
398
|
And use:
|
@@ -521,7 +555,7 @@ For large data sets, try [parallel reindexing](#parallel-reindexing).
|
|
521
555
|
|
522
556
|
- app starts
|
523
557
|
|
524
|
-
###
|
558
|
+
### Strategies
|
525
559
|
|
526
560
|
There are four strategies for keeping the index synced with your database.
|
527
561
|
|
@@ -587,11 +621,9 @@ class Image < ApplicationRecord
|
|
587
621
|
end
|
588
622
|
```
|
589
623
|
|
590
|
-
|
591
|
-
|
592
|
-
The best starting point to improve your search **by far** is to track searches and conversions.
|
624
|
+
## Intelligent Search
|
593
625
|
|
594
|
-
[Searchjoy](https://github.com/ankane/searchjoy) makes it easy.
|
626
|
+
The best starting point to improve your search **by far** is to track searches and conversions. [Searchjoy](https://github.com/ankane/searchjoy) makes it easy.
|
595
627
|
|
596
628
|
```ruby
|
597
629
|
Product.search "apple", track: {user_id: current_user.id}
|
@@ -604,15 +636,9 @@ Focus on:
|
|
604
636
|
- top searches with low conversions
|
605
637
|
- top searches with no results
|
606
638
|
|
607
|
-
|
608
|
-
|
609
|
-
Searchkick can use conversion data to learn what users are looking for. If a user searches for “ice cream” and adds Ben & Jerry’s Chunky Monkey to the cart (our conversion metric at Instacart), that item gets a little more weight for similar searches.
|
610
|
-
|
611
|
-
The first step is to define your conversion metric and start tracking conversions. The database works well for low volume, but feel free to use Redis or another datastore.
|
612
|
-
|
613
|
-
Searchkick automatically treats `apple` and `APPLE` the same.
|
639
|
+
Searchkick can then use the conversion data to learn what users are looking for. If a user searches for “ice cream” and adds Ben & Jerry’s Chunky Monkey to the cart (our conversion metric at Instacart), that item gets a little more weight for similar searches.
|
614
640
|
|
615
|
-
|
641
|
+
Add conversion data with:
|
616
642
|
|
617
643
|
```ruby
|
618
644
|
class Product < ApplicationRecord
|
@@ -636,9 +662,11 @@ Reindex and set up a cron job to add new conversions daily.
|
|
636
662
|
rake searchkick:reindex CLASS=Product
|
637
663
|
```
|
638
664
|
|
639
|
-
|
665
|
+
This can make a huge difference on the quality of your search.
|
640
666
|
|
641
|
-
|
667
|
+
For a more performant way to reindex conversion data, check out [performant conversions](#performant-conversions).
|
668
|
+
|
669
|
+
## Personalized Results
|
642
670
|
|
643
671
|
Order results differently for each user. For example, show a user’s previously purchased products before other results.
|
644
672
|
|
@@ -659,7 +687,7 @@ Reindex and search with:
|
|
659
687
|
Product.search "milk", boost_where: {orderer_ids: current_user.id}
|
660
688
|
```
|
661
689
|
|
662
|
-
|
690
|
+
## Instant Search / Autocomplete
|
663
691
|
|
664
692
|
Autocomplete predicts what a user will type, making the search experience faster and easier.
|
665
693
|
|
@@ -727,7 +755,7 @@ Then add the search box and JavaScript code to a view.
|
|
727
755
|
</script>
|
728
756
|
```
|
729
757
|
|
730
|
-
|
758
|
+
## Suggestions
|
731
759
|
|
732
760
|
![Suggest](https://gist.github.com/ankane/b6988db2802aca68a589b31e41b44195/raw/40febe948427e5bc53ec4e5dc248822855fef76f/recursion.png)
|
733
761
|
|
@@ -744,7 +772,7 @@ products = Product.search "peantu butta", suggest: true
|
|
744
772
|
products.suggestions # ["peanut butter"]
|
745
773
|
```
|
746
774
|
|
747
|
-
|
775
|
+
## Aggregations
|
748
776
|
|
749
777
|
[Aggregations](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html) provide aggregated search data.
|
750
778
|
|
@@ -817,10 +845,10 @@ Product.search "pear", aggs: {products_per_year: {date_histogram: {field: :creat
|
|
817
845
|
For other aggregation types, including sub-aggregations, use `body_options`:
|
818
846
|
|
819
847
|
```ruby
|
820
|
-
Product.search "orange", body_options: {aggs: {price: {histogram: {field: :price, interval: 10}}}
|
848
|
+
Product.search "orange", body_options: {aggs: {price: {histogram: {field: :price, interval: 10}}}}
|
821
849
|
```
|
822
850
|
|
823
|
-
|
851
|
+
## Highlight
|
824
852
|
|
825
853
|
Specify which fields to index with highlighting.
|
826
854
|
|
@@ -873,7 +901,7 @@ Band.search "cinema", fields: [:name], highlight: {fields: {name: {fragment_size
|
|
873
901
|
|
874
902
|
You can find available highlight options in the [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-highlighting.html#_highlighted_fragments).
|
875
903
|
|
876
|
-
|
904
|
+
## Similar Items
|
877
905
|
|
878
906
|
Find similar items.
|
879
907
|
|
@@ -882,7 +910,7 @@ product = Product.first
|
|
882
910
|
product.similar(fields: [:name], where: {size: "12 oz"})
|
883
911
|
```
|
884
912
|
|
885
|
-
|
913
|
+
## Geospatial Searches
|
886
914
|
|
887
915
|
```ruby
|
888
916
|
class Restaurant < ApplicationRecord
|
@@ -1049,10 +1077,170 @@ Product.search_index.tokens("dieg", analyzer: "searchkick_word_search")
|
|
1049
1077
|
|
1050
1078
|
See the [complete list of analyzers](https://github.com/ankane/searchkick/blob/31780ddac7a89eab1e0552a32b403f2040a37931/lib/searchkick/index_options.rb#L32).
|
1051
1079
|
|
1080
|
+
## Testing
|
1081
|
+
|
1082
|
+
As you iterate on your search, it’s a good idea to add tests.
|
1083
|
+
|
1084
|
+
For performance, only enable Searchkick callbacks for the tests that need it.
|
1085
|
+
|
1086
|
+
### Parallel Tests
|
1087
|
+
|
1088
|
+
Rails 6 enables parallel tests by default. Add to your `test/test_helper.rb`:
|
1089
|
+
|
1090
|
+
```ruby
|
1091
|
+
class ActiveSupport::TestCase
|
1092
|
+
parallelize_setup do |worker|
|
1093
|
+
Searchkick.index_suffix = worker
|
1094
|
+
|
1095
|
+
# reindex models
|
1096
|
+
Product.reindex
|
1097
|
+
|
1098
|
+
# and disable callbacks
|
1099
|
+
Searchkick.disable_callbacks
|
1100
|
+
end
|
1101
|
+
end
|
1102
|
+
```
|
1103
|
+
|
1104
|
+
And use:
|
1105
|
+
|
1106
|
+
```ruby
|
1107
|
+
class ProductTest < ActiveSupport::TestCase
|
1108
|
+
def setup
|
1109
|
+
Searchkick.enable_callbacks
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
def teardown
|
1113
|
+
Searchkick.disable_callbacks
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
def test_search
|
1117
|
+
Product.create!(name: "Apple")
|
1118
|
+
Product.search_index.refresh
|
1119
|
+
assert_equal ["Apple"], Product.search("apple").map(&:name)
|
1120
|
+
end
|
1121
|
+
end
|
1122
|
+
```
|
1123
|
+
|
1124
|
+
### Minitest
|
1125
|
+
|
1126
|
+
Add to your `test/test_helper.rb`:
|
1127
|
+
|
1128
|
+
```ruby
|
1129
|
+
# reindex models
|
1130
|
+
Product.reindex
|
1131
|
+
|
1132
|
+
# and disable callbacks
|
1133
|
+
Searchkick.disable_callbacks
|
1134
|
+
```
|
1135
|
+
|
1136
|
+
And use:
|
1137
|
+
|
1138
|
+
```ruby
|
1139
|
+
class ProductTest < Minitest::Test
|
1140
|
+
def setup
|
1141
|
+
Searchkick.enable_callbacks
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
def teardown
|
1145
|
+
Searchkick.disable_callbacks
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
def test_search
|
1149
|
+
Product.create!(name: "Apple")
|
1150
|
+
Product.search_index.refresh
|
1151
|
+
assert_equal ["Apple"], Product.search("apple").map(&:name)
|
1152
|
+
end
|
1153
|
+
end
|
1154
|
+
```
|
1155
|
+
|
1156
|
+
### RSpec
|
1157
|
+
|
1158
|
+
Add to your `spec/spec_helper.rb`:
|
1159
|
+
|
1160
|
+
```ruby
|
1161
|
+
RSpec.configure do |config|
|
1162
|
+
config.before(:suite) do
|
1163
|
+
# reindex models
|
1164
|
+
Product.reindex
|
1165
|
+
|
1166
|
+
# and disable callbacks
|
1167
|
+
Searchkick.disable_callbacks
|
1168
|
+
end
|
1169
|
+
|
1170
|
+
config.around(:each, search: true) do |example|
|
1171
|
+
Searchkick.callbacks(nil) do
|
1172
|
+
example.run
|
1173
|
+
end
|
1174
|
+
end
|
1175
|
+
end
|
1176
|
+
```
|
1177
|
+
|
1178
|
+
And use:
|
1179
|
+
|
1180
|
+
```ruby
|
1181
|
+
describe Product, search: true do
|
1182
|
+
it "searches" do
|
1183
|
+
Product.create!(name: "Apple")
|
1184
|
+
Product.search_index.refresh
|
1185
|
+
assert_equal ["Apple"], Product.search("apple").map(&:name)
|
1186
|
+
end
|
1187
|
+
end
|
1188
|
+
```
|
1189
|
+
|
1190
|
+
### Factory Bot
|
1191
|
+
|
1192
|
+
Use a trait and an after `create` hook for each indexed model:
|
1193
|
+
|
1194
|
+
```ruby
|
1195
|
+
FactoryBot.define do
|
1196
|
+
factory :product do
|
1197
|
+
# ...
|
1198
|
+
|
1199
|
+
# Note: This should be the last trait in the list so `reindex` is called
|
1200
|
+
# after all the other callbacks complete.
|
1201
|
+
trait :reindex do
|
1202
|
+
after(:create) do |product, _evaluator|
|
1203
|
+
product.reindex(refresh: true)
|
1204
|
+
end
|
1205
|
+
end
|
1206
|
+
end
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
# use it
|
1210
|
+
FactoryBot.create(:product, :some_trait, :reindex, some_attribute: "foo")
|
1211
|
+
```
|
1212
|
+
|
1213
|
+
### GitHub Actions
|
1214
|
+
|
1215
|
+
Check out [setup-elasticsearch](https://github.com/ankane/setup-elasticsearch) for an easy way to install Elasticsearch.
|
1216
|
+
|
1217
|
+
```yml
|
1218
|
+
- uses: ankane/setup-elasticsearch@v1
|
1219
|
+
```
|
1220
|
+
|
1052
1221
|
## Deployment
|
1053
1222
|
|
1054
1223
|
Searchkick uses `ENV["ELASTICSEARCH_URL"]` for the Elasticsearch server. This defaults to `http://localhost:9200`.
|
1055
1224
|
|
1225
|
+
- [Elastic Cloud](#elastic-cloud)
|
1226
|
+
- [Heroku](#heroku)
|
1227
|
+
- [Amazon Elasticsearch Service](#amazon-elasticsearch-service)
|
1228
|
+
- [Self-Hosted and Other](#self-hosted-and-other)
|
1229
|
+
|
1230
|
+
### Elastic Cloud
|
1231
|
+
|
1232
|
+
Create an initializer `config/initializers/elasticsearch.rb` with:
|
1233
|
+
|
1234
|
+
```ruby
|
1235
|
+
ENV["ELASTICSEARCH_URL"] = "https://user:password@host:port"
|
1236
|
+
```
|
1237
|
+
|
1238
|
+
Then deploy and reindex:
|
1239
|
+
|
1240
|
+
```sh
|
1241
|
+
rake searchkick:reindex:all
|
1242
|
+
```
|
1243
|
+
|
1056
1244
|
### Heroku
|
1057
1245
|
|
1058
1246
|
Choose an add-on: [Bonsai](https://elements.heroku.com/addons/bonsai), [SearchBox](https://elements.heroku.com/addons/searchbox), or [Elastic Cloud](https://elements.heroku.com/addons/foundelasticsearch).
|
@@ -1093,7 +1281,7 @@ heroku config:set ELASTICSEARCH_URL=https://elastic:password@12345.us-east-1.aws
|
|
1093
1281
|
Then deploy and reindex:
|
1094
1282
|
|
1095
1283
|
```sh
|
1096
|
-
heroku run rake searchkick:reindex
|
1284
|
+
heroku run rake searchkick:reindex:all
|
1097
1285
|
```
|
1098
1286
|
|
1099
1287
|
### Amazon Elasticsearch Service
|
@@ -1123,10 +1311,10 @@ Searchkick.aws_credentials = {
|
|
1123
1311
|
Then deploy and reindex:
|
1124
1312
|
|
1125
1313
|
```sh
|
1126
|
-
rake searchkick:reindex
|
1314
|
+
rake searchkick:reindex:all
|
1127
1315
|
```
|
1128
1316
|
|
1129
|
-
### Other
|
1317
|
+
### Self-Hosted and Other
|
1130
1318
|
|
1131
1319
|
Create an initializer `config/initializers/elasticsearch.rb` with:
|
1132
1320
|
|
@@ -1137,7 +1325,7 @@ ENV["ELASTICSEARCH_URL"] = "https://user:password@host:port"
|
|
1137
1325
|
Then deploy and reindex:
|
1138
1326
|
|
1139
1327
|
```sh
|
1140
|
-
rake searchkick:reindex
|
1328
|
+
rake searchkick:reindex:all
|
1141
1329
|
```
|
1142
1330
|
|
1143
1331
|
### Data Protection
|
@@ -1289,7 +1477,7 @@ Product.search_index.promote(index_name, update_refresh_interval: true)
|
|
1289
1477
|
|
1290
1478
|
### Queuing
|
1291
1479
|
|
1292
|
-
Push ids of records needing
|
1480
|
+
Push ids of records needing reindexing to a queue and reindex in bulk for better performance. First, set up Redis in an initializer. We recommend using [connection_pool](https://github.com/mperham/connection_pool).
|
1293
1481
|
|
1294
1482
|
```ruby
|
1295
1483
|
Searchkick.redis = ConnectionPool.new { Redis.new }
|
@@ -1517,6 +1705,10 @@ Boost specific models with:
|
|
1517
1705
|
indices_boost: {Category => 2, Product => 1}
|
1518
1706
|
```
|
1519
1707
|
|
1708
|
+
## Multi-Tenancy
|
1709
|
+
|
1710
|
+
Check out [this great post](https://www.tiagoamaro.com.br/2014/12/11/multi-tenancy-with-searchkick/) on the [Apartment](https://github.com/influitive/apartment) gem. Follow a similar pattern if you use another gem.
|
1711
|
+
|
1520
1712
|
## Scroll API
|
1521
1713
|
|
1522
1714
|
Searchkick also supports the [scroll API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html). Scrolling is not intended for real time user requests, but rather for processing large amounts of data.
|
@@ -1723,14 +1915,6 @@ class Product < ApplicationRecord
|
|
1723
1915
|
end
|
1724
1916
|
```
|
1725
1917
|
|
1726
|
-
Turn off stemming
|
1727
|
-
|
1728
|
-
```ruby
|
1729
|
-
class Product < ApplicationRecord
|
1730
|
-
searchkick stem: false
|
1731
|
-
end
|
1732
|
-
```
|
1733
|
-
|
1734
1918
|
Turn on stemming for conversions
|
1735
1919
|
|
1736
1920
|
```ruby
|
@@ -1739,14 +1923,6 @@ class Product < ApplicationRecord
|
|
1739
1923
|
end
|
1740
1924
|
```
|
1741
1925
|
|
1742
|
-
Use a different [similarity algorithm](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-similarity.html) for scoring
|
1743
|
-
|
1744
|
-
```ruby
|
1745
|
-
class Product < ApplicationRecord
|
1746
|
-
searchkick similarity: "classic"
|
1747
|
-
end
|
1748
|
-
```
|
1749
|
-
|
1750
1926
|
Make search case-sensitive
|
1751
1927
|
|
1752
1928
|
```ruby
|
@@ -1831,172 +2007,11 @@ Product.search "api", misspellings: {prefix_length: 2} # api, apt, no ahi
|
|
1831
2007
|
Product.search "ah", misspellings: {prefix_length: 2} # ah, no aha
|
1832
2008
|
```
|
1833
2009
|
|
1834
|
-
## Testing
|
1835
|
-
|
1836
|
-
For performance, only enable Searchkick callbacks for the tests that need it.
|
1837
|
-
|
1838
|
-
### Parallel Tests
|
1839
|
-
|
1840
|
-
Rails 6 enables parallel tests by default. Add to your `test/test_helper.rb`:
|
1841
|
-
|
1842
|
-
```ruby
|
1843
|
-
class ActiveSupport::TestCase
|
1844
|
-
parallelize_setup do |worker|
|
1845
|
-
Searchkick.index_suffix = worker
|
1846
|
-
|
1847
|
-
# reindex models
|
1848
|
-
Product.reindex
|
1849
|
-
|
1850
|
-
# and disable callbacks
|
1851
|
-
Searchkick.disable_callbacks
|
1852
|
-
end
|
1853
|
-
end
|
1854
|
-
```
|
1855
|
-
|
1856
|
-
And use:
|
1857
|
-
|
1858
|
-
```ruby
|
1859
|
-
class ProductTest < ActiveSupport::TestCase
|
1860
|
-
def setup
|
1861
|
-
Searchkick.enable_callbacks
|
1862
|
-
end
|
1863
|
-
|
1864
|
-
def teardown
|
1865
|
-
Searchkick.disable_callbacks
|
1866
|
-
end
|
1867
|
-
|
1868
|
-
def test_search
|
1869
|
-
Product.create!(name: "Apple")
|
1870
|
-
Product.search_index.refresh
|
1871
|
-
assert_equal ["Apple"], Product.search("apple").map(&:name)
|
1872
|
-
end
|
1873
|
-
end
|
1874
|
-
```
|
1875
|
-
|
1876
|
-
### Minitest
|
1877
|
-
|
1878
|
-
Add to your `test/test_helper.rb`:
|
1879
|
-
|
1880
|
-
```ruby
|
1881
|
-
# reindex models
|
1882
|
-
Product.reindex
|
1883
|
-
|
1884
|
-
# and disable callbacks
|
1885
|
-
Searchkick.disable_callbacks
|
1886
|
-
```
|
1887
|
-
|
1888
|
-
And use:
|
1889
|
-
|
1890
|
-
```ruby
|
1891
|
-
class ProductTest < Minitest::Test
|
1892
|
-
def setup
|
1893
|
-
Searchkick.enable_callbacks
|
1894
|
-
end
|
1895
|
-
|
1896
|
-
def teardown
|
1897
|
-
Searchkick.disable_callbacks
|
1898
|
-
end
|
1899
|
-
|
1900
|
-
def test_search
|
1901
|
-
Product.create!(name: "Apple")
|
1902
|
-
Product.search_index.refresh
|
1903
|
-
assert_equal ["Apple"], Product.search("apple").map(&:name)
|
1904
|
-
end
|
1905
|
-
end
|
1906
|
-
```
|
1907
|
-
|
1908
|
-
### RSpec
|
1909
|
-
|
1910
|
-
Add to your `spec/spec_helper.rb`:
|
1911
|
-
|
1912
|
-
```ruby
|
1913
|
-
RSpec.configure do |config|
|
1914
|
-
config.before(:suite) do
|
1915
|
-
# reindex models
|
1916
|
-
Product.reindex
|
1917
|
-
|
1918
|
-
# and disable callbacks
|
1919
|
-
Searchkick.disable_callbacks
|
1920
|
-
end
|
1921
|
-
|
1922
|
-
config.around(:each, search: true) do |example|
|
1923
|
-
Searchkick.callbacks(nil) do
|
1924
|
-
example.run
|
1925
|
-
end
|
1926
|
-
end
|
1927
|
-
end
|
1928
|
-
```
|
1929
|
-
|
1930
|
-
And use:
|
1931
|
-
|
1932
|
-
```ruby
|
1933
|
-
describe Product, search: true do
|
1934
|
-
it "searches" do
|
1935
|
-
Product.create!(name: "Apple")
|
1936
|
-
Product.search_index.refresh
|
1937
|
-
assert_equal ["Apple"], Product.search("apple").map(&:name)
|
1938
|
-
end
|
1939
|
-
end
|
1940
|
-
```
|
1941
|
-
|
1942
|
-
### Factory Bot
|
1943
|
-
|
1944
|
-
Use a trait and an after `create` hook for each indexed model:
|
1945
|
-
|
1946
|
-
```ruby
|
1947
|
-
FactoryBot.define do
|
1948
|
-
factory :product do
|
1949
|
-
# ...
|
1950
|
-
|
1951
|
-
# Note: This should be the last trait in the list so `reindex` is called
|
1952
|
-
# after all the other callbacks complete.
|
1953
|
-
trait :reindex do
|
1954
|
-
after(:create) do |product, _evaluator|
|
1955
|
-
product.reindex(refresh: true)
|
1956
|
-
end
|
1957
|
-
end
|
1958
|
-
end
|
1959
|
-
end
|
1960
|
-
|
1961
|
-
# use it
|
1962
|
-
FactoryBot.create(:product, :some_trait, :reindex, some_attribute: "foo")
|
1963
|
-
```
|
1964
|
-
|
1965
|
-
## Multi-Tenancy
|
1966
|
-
|
1967
|
-
Check out [this great post](https://www.tiagoamaro.com.br/2014/12/11/multi-tenancy-with-searchkick/) on the [Apartment](https://github.com/influitive/apartment) gem. Follow a similar pattern if you use another gem.
|
1968
|
-
|
1969
|
-
## Upgrading
|
1970
|
-
|
1971
|
-
See [how to upgrade to Searchkick 3](docs/Searchkick-3-Upgrade.md)
|
1972
|
-
|
1973
2010
|
## Elasticsearch 6 to 7 Upgrade
|
1974
2011
|
|
1975
2012
|
1. Install Searchkick 4
|
1976
2013
|
2. Upgrade your Elasticsearch cluster
|
1977
2014
|
|
1978
|
-
## Elasticsearch 5 to 6 Upgrade
|
1979
|
-
|
1980
|
-
Elasticsearch 6 removes the ability to reindex with the `_all` field. Before you upgrade, we recommend disabling this field manually and specifying default fields on your models.
|
1981
|
-
|
1982
|
-
```ruby
|
1983
|
-
class Product < ApplicationRecord
|
1984
|
-
searchkick _all: false, default_fields: [:name]
|
1985
|
-
end
|
1986
|
-
```
|
1987
|
-
|
1988
|
-
If you need search across multiple fields, we recommend creating a similar field in your search data.
|
1989
|
-
|
1990
|
-
```ruby
|
1991
|
-
class Product < ApplicationRecord
|
1992
|
-
def search_data
|
1993
|
-
{
|
1994
|
-
all: [name, size, quantity].join(" ")
|
1995
|
-
}
|
1996
|
-
end
|
1997
|
-
end
|
1998
|
-
```
|
1999
|
-
|
2000
2015
|
## Elasticsearch Gotchas
|
2001
2016
|
|
2002
2017
|
### Consistency
|
@@ -2045,3 +2060,5 @@ cd searchkick
|
|
2045
2060
|
bundle install
|
2046
2061
|
bundle exec rake test
|
2047
2062
|
```
|
2063
|
+
|
2064
|
+
Feel free to open an issue to get feedback on your idea before spending too much time on it.
|