searchkick 2.3.2 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -5
- data/CHANGELOG.md +7 -0
- data/README.md +68 -44
- data/lib/searchkick/index.rb +12 -4
- data/lib/searchkick/index_options.rb +8 -2
- data/lib/searchkick/model.rb +4 -2
- data/lib/searchkick/query.rb +13 -6
- data/lib/searchkick/version.rb +1 -1
- data/test/autocomplete_test.rb +6 -0
- data/test/inheritance_test.rb +1 -2
- data/test/match_test.rb +12 -0
- data/test/test_helper.rb +1 -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: 4bbb1863e16cb46d246eb067805b4a2cc1471c68
|
4
|
+
data.tar.gz: ea1bc2af0dcb8eb2e059aae9586697086a3cbc0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50d82877150dc9a875e8d67539f1992d29870b8cef227b7e81eb1c05f8e6e8346b952914035af8d2b1b5177cd8c730f5e55eb57c0a725feeaf0a2d6bfad6a29a
|
7
|
+
data.tar.gz: 45bea9181b909710ff9f446df5151f536e002caf11249d3d53c40ea7a1eecb465e797acf896c23ab15fc9b54f7028ce9d0244c1680dcb6f5281d7f3dc4f6d754
|
data/.travis.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
|
-
rvm: 2.
|
3
|
+
rvm: 2.4.2
|
4
4
|
services:
|
5
5
|
- mongodb
|
6
6
|
- redis-server
|
@@ -20,7 +20,7 @@ gemfile:
|
|
20
20
|
- test/gemfiles/mongoid5.gemfile
|
21
21
|
- test/gemfiles/mongoid6.gemfile
|
22
22
|
env:
|
23
|
-
- ELASTICSEARCH_VERSION=
|
23
|
+
- ELASTICSEARCH_VERSION=6.0.0
|
24
24
|
jdk: oraclejdk8
|
25
25
|
matrix:
|
26
26
|
include:
|
@@ -28,12 +28,11 @@ matrix:
|
|
28
28
|
env: ELASTICSEARCH_VERSION=2.0.0
|
29
29
|
jdk: oraclejdk7
|
30
30
|
- gemfile: Gemfile
|
31
|
-
env: ELASTICSEARCH_VERSION=2.4.
|
31
|
+
env: ELASTICSEARCH_VERSION=2.4.6
|
32
32
|
jdk: oraclejdk7
|
33
33
|
- gemfile: Gemfile
|
34
34
|
env: ELASTICSEARCH_VERSION=5.0.1
|
35
35
|
jdk: oraclejdk8
|
36
|
-
allow_failures:
|
37
36
|
- gemfile: Gemfile
|
38
|
-
env: ELASTICSEARCH_VERSION=6.
|
37
|
+
env: ELASTICSEARCH_VERSION=5.6.4
|
39
38
|
jdk: oraclejdk8
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -54,12 +54,12 @@ Add this line to your application’s Gemfile:
|
|
54
54
|
gem 'searchkick'
|
55
55
|
```
|
56
56
|
|
57
|
-
The latest version works with Elasticsearch 2 and
|
57
|
+
The latest version works with Elasticsearch 2, 5, and 6. For Elasticsearch 1, use version 1.5.1 and [this readme](https://github.com/ankane/searchkick/blob/v1.5.1/README.md).
|
58
58
|
|
59
59
|
Add searchkick to models you want to search.
|
60
60
|
|
61
61
|
```ruby
|
62
|
-
class Product <
|
62
|
+
class Product < ApplicationRecord
|
63
63
|
searchkick
|
64
64
|
end
|
65
65
|
```
|
@@ -73,7 +73,7 @@ Product.reindex
|
|
73
73
|
And to query, use:
|
74
74
|
|
75
75
|
```ruby
|
76
|
-
products = Product.search
|
76
|
+
products = Product.search("apples", fields: [:name])
|
77
77
|
products.each do |product|
|
78
78
|
puts product.name
|
79
79
|
end
|
@@ -130,6 +130,8 @@ Select
|
|
130
130
|
select: [:name]
|
131
131
|
```
|
132
132
|
|
133
|
+
[These source filtering options are supported](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html)
|
134
|
+
|
133
135
|
### Results
|
134
136
|
|
135
137
|
Searches return a `Searchkick::Results` object. This responds like an array to most methods.
|
@@ -236,7 +238,7 @@ Product.search "fresh honey", operator: "or" # fresh OR honey
|
|
236
238
|
By default, results must match the entire word - `back` will not match `backpack`. You can change this behavior with:
|
237
239
|
|
238
240
|
```ruby
|
239
|
-
class Product <
|
241
|
+
class Product < ApplicationRecord
|
240
242
|
searchkick word_start: [:name]
|
241
243
|
end
|
242
244
|
```
|
@@ -261,7 +263,7 @@ Available options are:
|
|
261
263
|
|
262
264
|
### Exact Matches
|
263
265
|
|
264
|
-
To match a field exactly (case-
|
266
|
+
To match a field exactly (case-sensitive), use:
|
265
267
|
|
266
268
|
```ruby
|
267
269
|
User.search query, fields: [{email: :exact}, :name]
|
@@ -280,7 +282,7 @@ User.search "fresh honey", match: :phrase
|
|
280
282
|
Searchkick defaults to English for stemming. To change this, use:
|
281
283
|
|
282
284
|
```ruby
|
283
|
-
class Product <
|
285
|
+
class Product < ApplicationRecord
|
284
286
|
searchkick language: "german"
|
285
287
|
end
|
286
288
|
```
|
@@ -290,7 +292,7 @@ end
|
|
290
292
|
### Synonyms
|
291
293
|
|
292
294
|
```ruby
|
293
|
-
class Product <
|
295
|
+
class Product < ApplicationRecord
|
294
296
|
searchkick synonyms: [["scallion", "green onion"], ["qtip", "cotton swab"]]
|
295
297
|
end
|
296
298
|
```
|
@@ -314,7 +316,7 @@ synonyms: ["lightbulb => halogenlamp"]
|
|
314
316
|
The above approach works well when your synonym list is static, but in practice, this is often not the case. When you analyze search conversions, you often want to add new synonyms or tags without a full reindex. You can use a library like [ActsAsTaggableOn](https://github.com/mbleigh/acts-as-taggable-on) and do:
|
315
317
|
|
316
318
|
```ruby
|
317
|
-
class Product <
|
319
|
+
class Product < ApplicationRecord
|
318
320
|
acts_as_taggable
|
319
321
|
scope :search_import, -> { includes(:tags) }
|
320
322
|
|
@@ -348,7 +350,7 @@ mv prolog/wn_s.pl /var/lib
|
|
348
350
|
Tell each model to use it:
|
349
351
|
|
350
352
|
```ruby
|
351
|
-
class Product <
|
353
|
+
class Product < ApplicationRecord
|
352
354
|
searchkick wordnet: true
|
353
355
|
end
|
354
356
|
```
|
@@ -417,7 +419,7 @@ Product.search "🍨🍰", emoji: true
|
|
417
419
|
Control what data is indexed with the `search_data` method. Call `Product.reindex` after changing this method.
|
418
420
|
|
419
421
|
```ruby
|
420
|
-
class Product <
|
422
|
+
class Product < ApplicationRecord
|
421
423
|
belongs_to :department
|
422
424
|
|
423
425
|
def search_data
|
@@ -433,7 +435,7 @@ end
|
|
433
435
|
Searchkick uses `find_in_batches` to import documents. To eager load associations, use the `search_import` scope.
|
434
436
|
|
435
437
|
```ruby
|
436
|
-
class Product <
|
438
|
+
class Product < ApplicationRecord
|
437
439
|
scope :search_import, -> { includes(:department) }
|
438
440
|
end
|
439
441
|
```
|
@@ -441,7 +443,7 @@ end
|
|
441
443
|
By default, all records are indexed. To control which records are indexed, use the `should_index?` method together with the `search_import` scope.
|
442
444
|
|
443
445
|
```ruby
|
444
|
-
class Product <
|
446
|
+
class Product < ApplicationRecord
|
445
447
|
scope :search_import, -> { where(active: true) }
|
446
448
|
|
447
449
|
def should_index?
|
@@ -483,7 +485,7 @@ There are four strategies for keeping the index synced with your database.
|
|
483
485
|
Use background jobs for better performance
|
484
486
|
|
485
487
|
```ruby
|
486
|
-
class Product <
|
488
|
+
class Product < ApplicationRecord
|
487
489
|
searchkick callbacks: :async
|
488
490
|
end
|
489
491
|
```
|
@@ -499,7 +501,7 @@ There are four strategies for keeping the index synced with your database.
|
|
499
501
|
Turn off automatic syncing
|
500
502
|
|
501
503
|
```ruby
|
502
|
-
class Product <
|
504
|
+
class Product < ApplicationRecord
|
503
505
|
searchkick callbacks: false
|
504
506
|
end
|
505
507
|
```
|
@@ -525,7 +527,7 @@ end
|
|
525
527
|
Data is **not** automatically synced when an association is updated. If this is desired, add a callback to reindex:
|
526
528
|
|
527
529
|
```ruby
|
528
|
-
class Image <
|
530
|
+
class Image < ApplicationRecord
|
529
531
|
belongs_to :product
|
530
532
|
|
531
533
|
after_commit :reindex_product
|
@@ -564,7 +566,7 @@ You do **not** need to clean up the search queries. Searchkick automatically tre
|
|
564
566
|
Next, add conversions to the index.
|
565
567
|
|
566
568
|
```ruby
|
567
|
-
class Product <
|
569
|
+
class Product < ApplicationRecord
|
568
570
|
has_many :searches, class_name: "Searchjoy::Search", as: :convertable
|
569
571
|
|
570
572
|
searchkick conversions: ["conversions"] # name of field
|
@@ -592,7 +594,7 @@ rake searchkick:reindex CLASS=Product
|
|
592
594
|
Order results differently for each user. For example, show a user’s previously purchased products before other results.
|
593
595
|
|
594
596
|
```ruby
|
595
|
-
class Product <
|
597
|
+
class Product < ApplicationRecord
|
596
598
|
def search_data
|
597
599
|
{
|
598
600
|
name: name,
|
@@ -621,7 +623,7 @@ Autocomplete predicts what a user will type, making the search experience faster
|
|
621
623
|
First, specify which fields use this feature. This is necessary since autocomplete can increase the index size significantly, but don’t worry - this gives you blazing faster queries.
|
622
624
|
|
623
625
|
```ruby
|
624
|
-
class Movie <
|
626
|
+
class Movie < ApplicationRecord
|
625
627
|
searchkick word_start: [:title, :director]
|
626
628
|
end
|
627
629
|
```
|
@@ -681,7 +683,7 @@ Then add the search box and JavaScript code to a view.
|
|
681
683
|
![Suggest](https://raw.githubusercontent.com/ankane/searchkick/gh-pages/recursion.png)
|
682
684
|
|
683
685
|
```ruby
|
684
|
-
class Product <
|
686
|
+
class Product < ApplicationRecord
|
685
687
|
searchkick suggest: [:name] # fields to generate suggestions
|
686
688
|
end
|
687
689
|
```
|
@@ -819,7 +821,7 @@ Product.search "pear", aggs: {products_per_year: {date_histogram: {field: :creat
|
|
819
821
|
Specify which fields to index with highlighting.
|
820
822
|
|
821
823
|
```ruby
|
822
|
-
class Product <
|
824
|
+
class Product < ApplicationRecord
|
823
825
|
searchkick highlight: [:name]
|
824
826
|
end
|
825
827
|
```
|
@@ -872,7 +874,7 @@ product.similar(fields: [:name], where: {size: "12 oz"})
|
|
872
874
|
### Geospatial Searches
|
873
875
|
|
874
876
|
```ruby
|
875
|
-
class Restaurant <
|
877
|
+
class Restaurant < ApplicationRecord
|
876
878
|
searchkick locations: [:location]
|
877
879
|
|
878
880
|
def search_data
|
@@ -918,7 +920,7 @@ Restaurant.search "wings", boost_by_distance: {location: {origin: {lat: 37, lon:
|
|
918
920
|
You can also index and search geo shapes.
|
919
921
|
|
920
922
|
```ruby
|
921
|
-
class Restaurant <
|
923
|
+
class Restaurant < ApplicationRecord
|
922
924
|
searchkick geo_shape: {
|
923
925
|
bounds: {tree: "geohash", precision: "1km"}
|
924
926
|
}
|
@@ -969,11 +971,19 @@ class Dog < Animal
|
|
969
971
|
end
|
970
972
|
```
|
971
973
|
|
974
|
+
In your parent model, set:
|
975
|
+
|
976
|
+
```ruby
|
977
|
+
class Animal < ApplicationRecord
|
978
|
+
searchkick inheritance: true
|
979
|
+
end
|
980
|
+
```
|
981
|
+
|
972
982
|
The parent and child model can both reindex.
|
973
983
|
|
974
984
|
```ruby
|
975
985
|
Animal.reindex
|
976
|
-
Dog.reindex # equivalent
|
986
|
+
Dog.reindex # equivalent, all animals reindexed
|
977
987
|
```
|
978
988
|
|
979
989
|
And to search, use:
|
@@ -1076,7 +1086,7 @@ ENV["ELASTICSEARCH_URL"] = "https://es-domain-1234.us-east-1.es.amazonaws.com"
|
|
1076
1086
|
To use signed request, include in your Gemfile:
|
1077
1087
|
|
1078
1088
|
```ruby
|
1079
|
-
gem 'faraday_middleware-aws-signers-v4'
|
1089
|
+
gem 'faraday_middleware-aws-signers-v4', '>= 0.1.9'
|
1080
1090
|
```
|
1081
1091
|
|
1082
1092
|
and add to your initializer:
|
@@ -1170,7 +1180,7 @@ If you run into issues on Windows, check out [this post](https://www.rastating.c
|
|
1170
1180
|
By default, all string fields are searchable (can be used in `fields` option). Speed up indexing and reduce index size by only making some fields searchable. This disables the `_all` field unless it’s listed.
|
1171
1181
|
|
1172
1182
|
```ruby
|
1173
|
-
class Product <
|
1183
|
+
class Product < ApplicationRecord
|
1174
1184
|
searchkick searchable: [:name]
|
1175
1185
|
end
|
1176
1186
|
```
|
@@ -1180,7 +1190,7 @@ end
|
|
1180
1190
|
By default, all string fields are filterable (can be used in `where` option). Speed up indexing and reduce index size by only making some fields filterable.
|
1181
1191
|
|
1182
1192
|
```ruby
|
1183
|
-
class Product <
|
1193
|
+
class Product < ApplicationRecord
|
1184
1194
|
searchkick filterable: [:brand]
|
1185
1195
|
end
|
1186
1196
|
```
|
@@ -1214,7 +1224,7 @@ And use:
|
|
1214
1224
|
Searchkick.reindex_status(index_name)
|
1215
1225
|
```
|
1216
1226
|
|
1217
|
-
You can also have Searchkick wait for reindexing to complete
|
1227
|
+
You can also have Searchkick wait for reindexing to complete
|
1218
1228
|
|
1219
1229
|
```ruby
|
1220
1230
|
Searchkick.reindex(async: {wait: true})
|
@@ -1265,7 +1275,7 @@ Searchkick.redis = ConnectionPool.new { Redis.new }
|
|
1265
1275
|
And ask your models to queue updates.
|
1266
1276
|
|
1267
1277
|
```ruby
|
1268
|
-
class Product <
|
1278
|
+
class Product < ApplicationRecord
|
1269
1279
|
searchkick callbacks: :queue
|
1270
1280
|
end
|
1271
1281
|
```
|
@@ -1289,7 +1299,7 @@ For more tips, check out [Keeping Elasticsearch in Sync](https://www.elastic.co/
|
|
1289
1299
|
Searchkick supports [Elasticsearch’s routing feature](https://www.elastic.co/blog/customizing-your-document-routing), which can significantly speed up searches.
|
1290
1300
|
|
1291
1301
|
```ruby
|
1292
|
-
class Business <
|
1302
|
+
class Business < ApplicationRecord
|
1293
1303
|
searchkick routing: true
|
1294
1304
|
|
1295
1305
|
def search_routing
|
@@ -1309,7 +1319,7 @@ Business.search "ice cream", routing: params[:city_id]
|
|
1309
1319
|
Reindex a subset of attributes to reduce time spent generating search data and cut down on network traffic.
|
1310
1320
|
|
1311
1321
|
```ruby
|
1312
|
-
class Product <
|
1322
|
+
class Product < ApplicationRecord
|
1313
1323
|
def search_data
|
1314
1324
|
{
|
1315
1325
|
name: name
|
@@ -1336,7 +1346,7 @@ Product.reindex(:search_prices)
|
|
1336
1346
|
Split out conversions into a separate method so you can use partial reindexing, and cache conversions to prevent N+1 queries. Be sure to use a centralized cache store like Memcached or Redis.
|
1337
1347
|
|
1338
1348
|
```ruby
|
1339
|
-
class Product <
|
1349
|
+
class Product < ApplicationRecord
|
1340
1350
|
def search_data
|
1341
1351
|
{
|
1342
1352
|
name: name
|
@@ -1401,7 +1411,7 @@ Searchkick makes it easy to use the Elasticsearch DSL on its own.
|
|
1401
1411
|
Create a custom mapping:
|
1402
1412
|
|
1403
1413
|
```ruby
|
1404
|
-
class Product <
|
1414
|
+
class Product < ApplicationRecord
|
1405
1415
|
searchkick mappings: {
|
1406
1416
|
product: {
|
1407
1417
|
properties: {
|
@@ -1416,7 +1426,7 @@ end
|
|
1416
1426
|
To keep the mappings and settings generated by Searchkick, use:
|
1417
1427
|
|
1418
1428
|
```ruby
|
1419
|
-
class Product <
|
1429
|
+
class Product < ApplicationRecord
|
1420
1430
|
searchkick merge_mappings: true, mappings: {...}
|
1421
1431
|
end
|
1422
1432
|
```
|
@@ -1542,7 +1552,7 @@ Product.search_index.clean_indices
|
|
1542
1552
|
Use custom settings
|
1543
1553
|
|
1544
1554
|
```ruby
|
1545
|
-
class Product <
|
1555
|
+
class Product < ApplicationRecord
|
1546
1556
|
searchkick settings: {number_of_shards: 3}
|
1547
1557
|
end
|
1548
1558
|
```
|
@@ -1550,7 +1560,7 @@ end
|
|
1550
1560
|
Use a different index name
|
1551
1561
|
|
1552
1562
|
```ruby
|
1553
|
-
class Product <
|
1563
|
+
class Product < ApplicationRecord
|
1554
1564
|
searchkick index_name: "products_v2"
|
1555
1565
|
end
|
1556
1566
|
```
|
@@ -1558,7 +1568,7 @@ end
|
|
1558
1568
|
Use a dynamic index name
|
1559
1569
|
|
1560
1570
|
```ruby
|
1561
|
-
class Product <
|
1571
|
+
class Product < ApplicationRecord
|
1562
1572
|
searchkick index_name: -> { "#{name.tableize}-#{I18n.locale}" }
|
1563
1573
|
end
|
1564
1574
|
```
|
@@ -1566,11 +1576,17 @@ end
|
|
1566
1576
|
Prefix the index name
|
1567
1577
|
|
1568
1578
|
```ruby
|
1569
|
-
class Product <
|
1579
|
+
class Product < ApplicationRecord
|
1570
1580
|
searchkick index_prefix: "datakick"
|
1571
1581
|
end
|
1572
1582
|
```
|
1573
1583
|
|
1584
|
+
For all models
|
1585
|
+
|
1586
|
+
```ruby
|
1587
|
+
Searchkick.index_prefix = "datakick"
|
1588
|
+
```
|
1589
|
+
|
1574
1590
|
Use a different term for boosting by conversions
|
1575
1591
|
|
1576
1592
|
```ruby
|
@@ -1580,7 +1596,7 @@ Product.search("banana", conversions_term: "organic banana")
|
|
1580
1596
|
Multiple conversion fields
|
1581
1597
|
|
1582
1598
|
```ruby
|
1583
|
-
class Product <
|
1599
|
+
class Product < ApplicationRecord
|
1584
1600
|
has_many :searches, class_name: "Searchjoy::Search"
|
1585
1601
|
|
1586
1602
|
# searchkick also supports multiple "conversions" fields
|
@@ -1636,16 +1652,24 @@ Eager load associations
|
|
1636
1652
|
Product.search "milk", includes: [:brand, :stores]
|
1637
1653
|
```
|
1638
1654
|
|
1639
|
-
Eager load different associations by model
|
1655
|
+
Eager load different associations by model
|
1640
1656
|
|
1641
1657
|
```ruby
|
1642
1658
|
Searchkick.search("*", index_name: [Product, Store], model_includes: {Product => [:store], Store => [:product]})
|
1643
1659
|
```
|
1644
1660
|
|
1661
|
+
Specify default fields to search
|
1662
|
+
|
1663
|
+
```ruby
|
1664
|
+
class Product < ApplicationRecord
|
1665
|
+
searchkick default_fields: [:name]
|
1666
|
+
end
|
1667
|
+
```
|
1668
|
+
|
1645
1669
|
Turn off special characters
|
1646
1670
|
|
1647
1671
|
```ruby
|
1648
|
-
class Product <
|
1672
|
+
class Product < ApplicationRecord
|
1649
1673
|
# A will not match Ä
|
1650
1674
|
searchkick special_characters: false
|
1651
1675
|
end
|
@@ -1654,7 +1678,7 @@ end
|
|
1654
1678
|
Use a different [similarity algorithm](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-similarity.html) for scoring
|
1655
1679
|
|
1656
1680
|
```ruby
|
1657
|
-
class Product <
|
1681
|
+
class Product < ApplicationRecord
|
1658
1682
|
searchkick similarity: "classic"
|
1659
1683
|
end
|
1660
1684
|
```
|
@@ -1662,7 +1686,7 @@ end
|
|
1662
1686
|
Change import batch size
|
1663
1687
|
|
1664
1688
|
```ruby
|
1665
|
-
class Product <
|
1689
|
+
class Product < ApplicationRecord
|
1666
1690
|
searchkick batch_size: 200 # defaults to 1000
|
1667
1691
|
end
|
1668
1692
|
```
|
@@ -1689,7 +1713,7 @@ Product.search("carrots", request_params: {search_type: "dfs_query_then_fetch"})
|
|
1689
1713
|
Reindex conditionally
|
1690
1714
|
|
1691
1715
|
```ruby
|
1692
|
-
class Product <
|
1716
|
+
class Product < ApplicationRecord
|
1693
1717
|
searchkick callbacks: false
|
1694
1718
|
|
1695
1719
|
# add the callbacks manually
|
@@ -1891,7 +1915,7 @@ Product.search_index.refresh
|
|
1891
1915
|
Due to the distributed nature of Elasticsearch, you can get incorrect results when the number of documents in the index is low. You can [read more about it here](https://www.elastic.co/blog/understanding-query-then-fetch-vs-dfs-query-then-fetch). To fix this, do:
|
1892
1916
|
|
1893
1917
|
```ruby
|
1894
|
-
class Product <
|
1918
|
+
class Product < ApplicationRecord
|
1895
1919
|
searchkick settings: {number_of_shards: 1}
|
1896
1920
|
end
|
1897
1921
|
```
|
data/lib/searchkick/index.rb
CHANGED
@@ -318,10 +318,14 @@ module Searchkick
|
|
318
318
|
client.indices.analyze(body: {text: text}.merge(options), index: name)["tokens"].map { |t| t["token"] }
|
319
319
|
end
|
320
320
|
|
321
|
-
def klass_document_type(klass)
|
322
|
-
@klass_document_type[klass] ||= begin
|
321
|
+
def klass_document_type(klass, ignore_type = false)
|
322
|
+
@klass_document_type[[klass, ignore_type]] ||= begin
|
323
323
|
if klass.respond_to?(:document_type)
|
324
324
|
klass.document_type
|
325
|
+
elsif !ignore_type && klass.searchkick_klass.searchkick_options[:_type]
|
326
|
+
type = klass.searchkick_klass.searchkick_options[:_type]
|
327
|
+
type = type.call if type.respond_to?(:call)
|
328
|
+
type
|
325
329
|
else
|
326
330
|
klass.model_name.to_s.underscore
|
327
331
|
end
|
@@ -334,11 +338,11 @@ module Searchkick
|
|
334
338
|
Searchkick.client
|
335
339
|
end
|
336
340
|
|
337
|
-
def document_type(record)
|
341
|
+
def document_type(record, ignore_type = false)
|
338
342
|
if record.respond_to?(:search_document_type)
|
339
343
|
record.search_document_type
|
340
344
|
else
|
341
|
-
klass_document_type(record.class)
|
345
|
+
klass_document_type(record.class, ignore_type)
|
342
346
|
end
|
343
347
|
end
|
344
348
|
|
@@ -386,6 +390,10 @@ module Searchkick
|
|
386
390
|
end
|
387
391
|
end
|
388
392
|
|
393
|
+
if !source.key?("type") && record.class.searchkick_klass.searchkick_options[:inheritance]
|
394
|
+
source["type"] = document_type(record, true)
|
395
|
+
end
|
396
|
+
|
389
397
|
cast_big_decimal(source)
|
390
398
|
|
391
399
|
source
|
@@ -4,6 +4,8 @@ module Searchkick
|
|
4
4
|
options = @options
|
5
5
|
language = options[:language]
|
6
6
|
language = language.call if language.respond_to?(:call)
|
7
|
+
type = options[:_type] || :_default_
|
8
|
+
type = type.call if type.respond_to?(:call)
|
7
9
|
|
8
10
|
if options[:mappings] && !options[:merge_mappings]
|
9
11
|
settings = options[:settings] || {}
|
@@ -275,6 +277,10 @@ module Searchkick
|
|
275
277
|
mapping[field] = shape_options.merge(type: "geo_shape")
|
276
278
|
end
|
277
279
|
|
280
|
+
if options[:inheritance]
|
281
|
+
mapping[:type] = keyword_mapping
|
282
|
+
end
|
283
|
+
|
278
284
|
routing = {}
|
279
285
|
if options[:routing]
|
280
286
|
routing = {required: true}
|
@@ -313,7 +319,7 @@ module Searchkick
|
|
313
319
|
multi_field = dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}"))
|
314
320
|
|
315
321
|
mappings = {
|
316
|
-
|
322
|
+
type => {
|
317
323
|
properties: mapping,
|
318
324
|
_routing: routing,
|
319
325
|
# https://gist.github.com/kimchy/2898285
|
@@ -331,7 +337,7 @@ module Searchkick
|
|
331
337
|
|
332
338
|
if below60
|
333
339
|
all_enabled = all && (!options[:searchable] || options[:searchable].to_a.map(&:to_s).include?("_all"))
|
334
|
-
mappings[
|
340
|
+
mappings[type][:_all] = all_enabled ? analyzed_field_options : {enabled: false}
|
335
341
|
end
|
336
342
|
|
337
343
|
mappings = mappings.deep_merge(options[:mappings] || {})
|
data/lib/searchkick/model.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Searchkick
|
2
2
|
module Model
|
3
3
|
def searchkick(**options)
|
4
|
-
unknown_keywords = options.keys - [:_all, :batch_size, :callbacks, :conversions, :default_fields,
|
5
|
-
:filterable, :geo_shape, :highlight, :ignore_above, :index_name, :index_prefix, :language,
|
4
|
+
unknown_keywords = options.keys - [:_all, :_type, :batch_size, :callbacks, :conversions, :default_fields,
|
5
|
+
:filterable, :geo_shape, :highlight, :ignore_above, :index_name, :index_prefix, :inheritance, :language,
|
6
6
|
:locations, :mappings, :match, :merge_mappings, :routing, :searchable, :settings, :similarity,
|
7
7
|
:special_characters, :stem_conversions, :suggest, :synonyms, :text_end,
|
8
8
|
:text_middle, :text_start, :word, :wordnet, :word_end, :word_middle, :word_start]
|
@@ -12,6 +12,8 @@ module Searchkick
|
|
12
12
|
|
13
13
|
Searchkick.models << self
|
14
14
|
|
15
|
+
options[:_type] ||= -> { searchkick_index.klass_document_type(self, true) } if options[:inheritance]
|
16
|
+
|
15
17
|
class_eval do
|
16
18
|
cattr_reader :searchkick_options, :searchkick_klass
|
17
19
|
|
data/lib/searchkick/query.rb
CHANGED
@@ -233,7 +233,7 @@ module Searchkick
|
|
233
233
|
if options[:similar]
|
234
234
|
payload = {
|
235
235
|
more_like_this: {
|
236
|
-
|
236
|
+
like: term,
|
237
237
|
min_doc_freq: 1,
|
238
238
|
min_term_freq: 1,
|
239
239
|
analyzer: "searchkick_search2"
|
@@ -307,7 +307,7 @@ module Searchkick
|
|
307
307
|
exclude_field = field
|
308
308
|
|
309
309
|
if field == "_all" || field.end_with?(".analyzed")
|
310
|
-
shared_options[:cutoff_frequency] = 0.001 unless operator == "and" || misspellings == false
|
310
|
+
shared_options[:cutoff_frequency] = 0.001 unless operator.to_s == "and" || misspellings == false
|
311
311
|
qs.concat [
|
312
312
|
shared_options.merge(analyzer: "searchkick_search"),
|
313
313
|
shared_options.merge(analyzer: "searchkick_search2")
|
@@ -449,8 +449,14 @@ module Searchkick
|
|
449
449
|
# indices_boost
|
450
450
|
set_boost_by_indices(payload)
|
451
451
|
|
452
|
+
# type when inheritance
|
453
|
+
where = (options[:where] || {}).dup
|
454
|
+
if searchkick_options[:inheritance] && (options[:type] || (klass != searchkick_klass && searchkick_index))
|
455
|
+
where[:type] = [options[:type] || klass].flatten.map { |v| searchkick_index.klass_document_type(v, true) }
|
456
|
+
end
|
457
|
+
|
452
458
|
# filters
|
453
|
-
filters = where_filters(
|
459
|
+
filters = where_filters(where)
|
454
460
|
set_filters(payload, filters) if filters.any?
|
455
461
|
|
456
462
|
# aggregations
|
@@ -466,8 +472,7 @@ module Searchkick
|
|
466
472
|
payload[:timeout] ||= "#{Searchkick.search_timeout + 1}s"
|
467
473
|
|
468
474
|
# An empty array will cause only the _id and _type for each hit to be returned
|
469
|
-
#
|
470
|
-
# doc for :select_v2 - https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html
|
475
|
+
# https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html
|
471
476
|
if options[:select]
|
472
477
|
if options[:select] == []
|
473
478
|
# intuitively [] makes sense to return no fields, but ES by default returns all fields
|
@@ -481,7 +486,7 @@ module Searchkick
|
|
481
486
|
end
|
482
487
|
|
483
488
|
# type
|
484
|
-
if options[:type] || (klass != searchkick_klass && searchkick_index)
|
489
|
+
if !searchkick_options[:inheritance] && (options[:type] || (klass != searchkick_klass && searchkick_index))
|
485
490
|
@type = [options[:type] || klass].flatten.map { |v| searchkick_index.klass_document_type(v) }
|
486
491
|
end
|
487
492
|
|
@@ -516,6 +521,8 @@ module Searchkick
|
|
516
521
|
["_all"]
|
517
522
|
elsif all && default_match == :phrase
|
518
523
|
["_all.phrase"]
|
524
|
+
elsif term == "*"
|
525
|
+
[]
|
519
526
|
else
|
520
527
|
raise ArgumentError, "Must specify fields to search"
|
521
528
|
end
|
data/lib/searchkick/version.rb
CHANGED
data/test/autocomplete_test.rb
CHANGED
@@ -72,4 +72,10 @@ class AutocompleteTest < Minitest::Test
|
|
72
72
|
store_names ["hi@example.org"]
|
73
73
|
assert_search "hi@example.org", ["hi@example.org"], fields: [{name: :exact}]
|
74
74
|
end
|
75
|
+
|
76
|
+
def test_exact_case
|
77
|
+
store_names ["Hello"]
|
78
|
+
assert_search "hello", [], fields: [{name: :exact}]
|
79
|
+
assert_search "Hello", ["Hello"], fields: [{name: :exact}]
|
80
|
+
end
|
75
81
|
end
|
data/test/inheritance_test.rb
CHANGED
@@ -9,7 +9,6 @@ class InheritanceTest < Minitest::Test
|
|
9
9
|
def test_child_reindex
|
10
10
|
store_names ["Max"], Cat
|
11
11
|
assert Dog.reindex
|
12
|
-
Animal.searchkick_index.refresh
|
13
12
|
assert_equal 1, Animal.search("*").size
|
14
13
|
end
|
15
14
|
|
@@ -70,7 +69,7 @@ class InheritanceTest < Minitest::Test
|
|
70
69
|
store_names ["Bear A"], Cat
|
71
70
|
store_names ["Bear B"], Dog
|
72
71
|
Animal.reindex
|
73
|
-
assert_equal
|
72
|
+
assert_equal 2, Animal.search("bear").size
|
74
73
|
end
|
75
74
|
|
76
75
|
# TODO move somewhere better
|
data/test/match_test.rb
CHANGED
@@ -18,6 +18,13 @@ class MatchTest < Minitest::Test
|
|
18
18
|
assert_search "pepperjack cheese skewers", ["Pepper Jack Cheese Skewers"]
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_operator
|
22
|
+
store_names ["fresh", "honey"]
|
23
|
+
assert_search "fresh honey", ["fresh", "honey"], {operator: "or"}
|
24
|
+
assert_search "fresh honey", [], {operator: "and"}
|
25
|
+
assert_search "fresh honey", ["fresh", "honey"], {operator: :or}
|
26
|
+
end
|
27
|
+
|
21
28
|
# def test_cheese_space_in_query
|
22
29
|
# store_names ["Pepperjack Cheese Skewers"]
|
23
30
|
# assert_search "pepper jack cheese skewers", ["Pepperjack Cheese Skewers"]
|
@@ -238,6 +245,11 @@ class MatchTest < Minitest::Test
|
|
238
245
|
assert_search "fresh honey", ["Fresh Honey"], match: :phrase
|
239
246
|
end
|
240
247
|
|
248
|
+
def test_phrase_again
|
249
|
+
store_names ["Social entrepreneurs don't have it easy raising capital"]
|
250
|
+
assert_search "social entrepreneurs don't have it easy raising capital", ["Social entrepreneurs don't have it easy raising capital"], match: :phrase
|
251
|
+
end
|
252
|
+
|
241
253
|
def test_phrase_order
|
242
254
|
store_names ["Wheat Bread", "Whole Wheat Bread"]
|
243
255
|
assert_order "wheat bread", ["Wheat Bread", "Whole Wheat Bread"], match: :phrase
|
data/test/test_helper.rb
CHANGED
@@ -505,6 +505,7 @@ end
|
|
505
505
|
class Animal
|
506
506
|
searchkick \
|
507
507
|
default_fields: elasticsearch_below60? ? nil : [:name],
|
508
|
+
inheritance: !elasticsearch_below60?,
|
508
509
|
text_start: [:name],
|
509
510
|
suggest: [:name],
|
510
511
|
index_name: -> { "#{name.tableize}-#{Date.today.year}#{Searchkick.index_suffix}" },
|
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: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|