searchkick 5.0.1 → 5.0.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 +4 -0
- data/README.md +62 -60
- data/lib/searchkick/model.rb +2 -2
- data/lib/searchkick/relation.rb +80 -4
- data/lib/searchkick/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ebb326348913a8532f1f4e7771bcdb57dda1abe4cc668e4f5bf8fe44bdbc85b
|
4
|
+
data.tar.gz: 57b63c4444b9dbe26bb8decc4ab4dca81e4e037e6642d5728b96549aea0b2131
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f901dfae13328bb168e60cc72559ee2fd624f801456fee1628272c83ed402c4d00a83d3cac2ba978e6ce67c76853ca2dc5c1c0048b11ac34d74bb2b18bc3b974
|
7
|
+
data.tar.gz: '086eb84edef491f27c254cb09ee5bce9ec07bcec46f79b2ca65404041e67bfccd877e30e92e6393ca2117c353ec71e8c632c50615c71e481e89c30c071934dd5'
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -98,7 +98,7 @@ Searchkick supports the complete [Elasticsearch Search API](https://www.elastic.
|
|
98
98
|
Query like SQL
|
99
99
|
|
100
100
|
```ruby
|
101
|
-
Product.search
|
101
|
+
Product.search("apples", where: {in_stock: true}, limit: 10, offset: 50)
|
102
102
|
```
|
103
103
|
|
104
104
|
Search specific fields
|
@@ -226,7 +226,7 @@ You can also boost by:
|
|
226
226
|
Use a `*` for the query.
|
227
227
|
|
228
228
|
```ruby
|
229
|
-
Product.search
|
229
|
+
Product.search("*")
|
230
230
|
```
|
231
231
|
|
232
232
|
### Pagination
|
@@ -235,7 +235,7 @@ Plays nicely with kaminari and will_paginate.
|
|
235
235
|
|
236
236
|
```ruby
|
237
237
|
# controller
|
238
|
-
@products = Product.search
|
238
|
+
@products = Product.search("milk", page: params[:page], per_page: 20)
|
239
239
|
```
|
240
240
|
|
241
241
|
View with kaminari
|
@@ -255,13 +255,13 @@ View with will_paginate
|
|
255
255
|
By default, results must match all words in the query.
|
256
256
|
|
257
257
|
```ruby
|
258
|
-
Product.search
|
258
|
+
Product.search("fresh honey") # fresh AND honey
|
259
259
|
```
|
260
260
|
|
261
261
|
To change this, use:
|
262
262
|
|
263
263
|
```ruby
|
264
|
-
Product.search
|
264
|
+
Product.search("fresh honey", operator: "or") # fresh OR honey
|
265
265
|
```
|
266
266
|
|
267
267
|
By default, results must match the entire word - `back` will not match `backpack`. You can change this behavior with:
|
@@ -275,7 +275,7 @@ end
|
|
275
275
|
And to search (after you reindex):
|
276
276
|
|
277
277
|
```ruby
|
278
|
-
Product.search
|
278
|
+
Product.search("back", fields: [:name], match: :word_start)
|
279
279
|
```
|
280
280
|
|
281
281
|
Available options are:
|
@@ -297,7 +297,7 @@ The default is `:word`. The most matches will happen with `:word_middle`.
|
|
297
297
|
To match a field exactly (case-sensitive), use:
|
298
298
|
|
299
299
|
```ruby
|
300
|
-
|
300
|
+
Product.search(query, fields: [{email: :exact}, :name])
|
301
301
|
```
|
302
302
|
|
303
303
|
### Phrase Matches
|
@@ -305,7 +305,7 @@ User.search query, fields: [{email: :exact}, :name]
|
|
305
305
|
To only match the exact order, use:
|
306
306
|
|
307
307
|
```ruby
|
308
|
-
|
308
|
+
Product.search("fresh honey", match: :phrase)
|
309
309
|
```
|
310
310
|
|
311
311
|
### Stemming and Language
|
@@ -426,7 +426,7 @@ end
|
|
426
426
|
Search with:
|
427
427
|
|
428
428
|
```ruby
|
429
|
-
Product.search
|
429
|
+
Product.search(query, fields: [:name_tagged])
|
430
430
|
```
|
431
431
|
|
432
432
|
### Misspellings
|
@@ -436,13 +436,13 @@ By default, Searchkick handles misspelled queries by returning results with an [
|
|
436
436
|
You can change this with:
|
437
437
|
|
438
438
|
```ruby
|
439
|
-
Product.search
|
439
|
+
Product.search("zucini", misspellings: {edit_distance: 2}) # zucchini
|
440
440
|
```
|
441
441
|
|
442
442
|
To prevent poor precision and improve performance for correctly spelled queries (which should be a majority for most applications), Searchkick can first perform a search without misspellings, and if there are too few results, perform another with them.
|
443
443
|
|
444
444
|
```ruby
|
445
|
-
Product.search
|
445
|
+
Product.search("zuchini", misspellings: {below: 5})
|
446
446
|
```
|
447
447
|
|
448
448
|
If there are fewer than 5 results, a 2nd search is performed with misspellings enabled. The result of this query is returned.
|
@@ -450,13 +450,13 @@ If there are fewer than 5 results, a 2nd search is performed with misspellings e
|
|
450
450
|
Turn off misspellings with:
|
451
451
|
|
452
452
|
```ruby
|
453
|
-
Product.search
|
453
|
+
Product.search("zuchini", misspellings: false) # no zucchini
|
454
454
|
```
|
455
455
|
|
456
456
|
Specify which fields can include misspellings with:
|
457
457
|
|
458
458
|
```ruby
|
459
|
-
Product.search
|
459
|
+
Product.search("zucini", fields: [:name, :color], misspellings: {fields: [:name]})
|
460
460
|
```
|
461
461
|
|
462
462
|
> When doing this, you must also specify fields to search
|
@@ -466,7 +466,7 @@ Product.search "zucini", fields: [:name, :color], misspellings: {fields: [:name]
|
|
466
466
|
If a user searches `butter`, they may also get results for `peanut butter`. To prevent this, use:
|
467
467
|
|
468
468
|
```ruby
|
469
|
-
Product.search
|
469
|
+
Product.search("butter", exclude: ["peanut butter"])
|
470
470
|
```
|
471
471
|
|
472
472
|
You can map queries and terms to exclude with:
|
@@ -477,7 +477,7 @@ exclude_queries = {
|
|
477
477
|
"cream" => ["ice cream", "whipped cream"]
|
478
478
|
}
|
479
479
|
|
480
|
-
Product.search
|
480
|
+
Product.search(query, exclude: exclude_queries[query])
|
481
481
|
```
|
482
482
|
|
483
483
|
You can demote results by boosting by a factor less than one:
|
@@ -499,7 +499,7 @@ gem "gemoji-parser"
|
|
499
499
|
And use:
|
500
500
|
|
501
501
|
```ruby
|
502
|
-
Product.search
|
502
|
+
Product.search("🍨🍰", emoji: true)
|
503
503
|
```
|
504
504
|
|
505
505
|
## Indexing
|
@@ -651,7 +651,7 @@ end
|
|
651
651
|
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.
|
652
652
|
|
653
653
|
```ruby
|
654
|
-
Product.search
|
654
|
+
Product.search("apple", track: {user_id: current_user.id})
|
655
655
|
```
|
656
656
|
|
657
657
|
[See the docs](https://github.com/ankane/searchjoy) for how to install and use.
|
@@ -709,7 +709,7 @@ end
|
|
709
709
|
Reindex and search with:
|
710
710
|
|
711
711
|
```ruby
|
712
|
-
Product.search
|
712
|
+
Product.search("milk", boost_where: {orderer_ids: current_user.id})
|
713
713
|
```
|
714
714
|
|
715
715
|
## Instant Search / Autocomplete
|
@@ -733,7 +733,7 @@ end
|
|
733
733
|
Reindex and search with:
|
734
734
|
|
735
735
|
```ruby
|
736
|
-
Movie.search
|
736
|
+
Movie.search("jurassic pa", fields: [:title], match: :word_start)
|
737
737
|
```
|
738
738
|
|
739
739
|
Typically, you want to use a JavaScript library like [typeahead.js](https://twitter.github.io/typeahead.js/) or [jQuery UI](https://jqueryui.com/autocomplete/).
|
@@ -793,7 +793,7 @@ end
|
|
793
793
|
Reindex and search with:
|
794
794
|
|
795
795
|
```ruby
|
796
|
-
products = Product.search
|
796
|
+
products = Product.search("peantu butta", suggest: true)
|
797
797
|
products.suggestions # ["peanut butter"]
|
798
798
|
```
|
799
799
|
|
@@ -804,40 +804,40 @@ products.suggestions # ["peanut butter"]
|
|
804
804
|

|
805
805
|
|
806
806
|
```ruby
|
807
|
-
products = Product.search
|
807
|
+
products = Product.search("chuck taylor", aggs: [:product_type, :gender, :brand])
|
808
808
|
products.aggs
|
809
809
|
```
|
810
810
|
|
811
811
|
By default, `where` conditions apply to aggregations.
|
812
812
|
|
813
813
|
```ruby
|
814
|
-
Product.search
|
814
|
+
Product.search("wingtips", where: {color: "brandy"}, aggs: [:size])
|
815
815
|
# aggregations for brandy wingtips are returned
|
816
816
|
```
|
817
817
|
|
818
818
|
Change this with:
|
819
819
|
|
820
820
|
```ruby
|
821
|
-
Product.search
|
821
|
+
Product.search("wingtips", where: {color: "brandy"}, aggs: [:size], smart_aggs: false)
|
822
822
|
# aggregations for all wingtips are returned
|
823
823
|
```
|
824
824
|
|
825
825
|
Set `where` conditions for each aggregation separately with:
|
826
826
|
|
827
827
|
```ruby
|
828
|
-
Product.search
|
828
|
+
Product.search("wingtips", aggs: {size: {where: {color: "brandy"}}})
|
829
829
|
```
|
830
830
|
|
831
831
|
Limit
|
832
832
|
|
833
833
|
```ruby
|
834
|
-
Product.search
|
834
|
+
Product.search("apples", aggs: {store_id: {limit: 10}})
|
835
835
|
```
|
836
836
|
|
837
837
|
Order
|
838
838
|
|
839
839
|
```ruby
|
840
|
-
Product.search
|
840
|
+
Product.search("wingtips", aggs: {color: {order: {"_key" => "asc"}}}) # alphabetically
|
841
841
|
```
|
842
842
|
|
843
843
|
[All of these options are supported](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-order)
|
@@ -846,31 +846,31 @@ Ranges
|
|
846
846
|
|
847
847
|
```ruby
|
848
848
|
price_ranges = [{to: 20}, {from: 20, to: 50}, {from: 50}]
|
849
|
-
Product.search
|
849
|
+
Product.search("*", aggs: {price: {ranges: price_ranges}})
|
850
850
|
```
|
851
851
|
|
852
852
|
Minimum document count
|
853
853
|
|
854
854
|
```ruby
|
855
|
-
Product.search
|
855
|
+
Product.search("apples", aggs: {store_id: {min_doc_count: 2}})
|
856
856
|
```
|
857
857
|
|
858
858
|
Script support
|
859
859
|
|
860
860
|
```ruby
|
861
|
-
Product.search
|
861
|
+
Product.search("*", aggs: {color: {script: {source: "'Color: ' + _value"}}})
|
862
862
|
```
|
863
863
|
|
864
864
|
Date histogram
|
865
865
|
|
866
866
|
```ruby
|
867
|
-
Product.search
|
867
|
+
Product.search("pear", aggs: {products_per_year: {date_histogram: {field: :created_at, interval: :year}}})
|
868
868
|
```
|
869
869
|
|
870
870
|
For other aggregation types, including sub-aggregations, use `body_options`:
|
871
871
|
|
872
872
|
```ruby
|
873
|
-
Product.search
|
873
|
+
Product.search("orange", body_options: {aggs: {price: {histogram: {field: :price, interval: 10}}}})
|
874
874
|
```
|
875
875
|
|
876
876
|
## Highlight
|
@@ -878,7 +878,7 @@ Product.search "orange", body_options: {aggs: {price: {histogram: {field: :price
|
|
878
878
|
Specify which fields to index with highlighting.
|
879
879
|
|
880
880
|
```ruby
|
881
|
-
class
|
881
|
+
class Band < ApplicationRecord
|
882
882
|
searchkick highlight: [:name]
|
883
883
|
end
|
884
884
|
```
|
@@ -886,7 +886,7 @@ end
|
|
886
886
|
Highlight the search query in the results.
|
887
887
|
|
888
888
|
```ruby
|
889
|
-
bands = Band.search
|
889
|
+
bands = Band.search("cinema", highlight: true)
|
890
890
|
```
|
891
891
|
|
892
892
|
View the highlighted fields with:
|
@@ -900,19 +900,19 @@ end
|
|
900
900
|
To change the tag, use:
|
901
901
|
|
902
902
|
```ruby
|
903
|
-
Band.search
|
903
|
+
Band.search("cinema", highlight: {tag: "<strong>"})
|
904
904
|
```
|
905
905
|
|
906
906
|
To highlight and search different fields, use:
|
907
907
|
|
908
908
|
```ruby
|
909
|
-
Band.search
|
909
|
+
Band.search("cinema", fields: [:name], highlight: {fields: [:description]})
|
910
910
|
```
|
911
911
|
|
912
912
|
By default, the entire field is highlighted. To get small snippets instead, use:
|
913
913
|
|
914
914
|
```ruby
|
915
|
-
bands = Band.search
|
915
|
+
bands = Band.search("cinema", highlight: {fragment_size: 20})
|
916
916
|
bands.with_highlights(multiple: true).each do |band, highlights|
|
917
917
|
highlights[:name].join(" and ")
|
918
918
|
end
|
@@ -921,7 +921,7 @@ end
|
|
921
921
|
Additional options can be specified for each field:
|
922
922
|
|
923
923
|
```ruby
|
924
|
-
Band.search
|
924
|
+
Band.search("cinema", fields: [:name], highlight: {fields: {name: {fragment_size: 200}}})
|
925
925
|
```
|
926
926
|
|
927
927
|
You can find available highlight options in the [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/highlighting.html).
|
@@ -950,13 +950,13 @@ end
|
|
950
950
|
Reindex and search with:
|
951
951
|
|
952
952
|
```ruby
|
953
|
-
Restaurant.search
|
953
|
+
Restaurant.search("pizza", where: {location: {near: {lat: 37, lon: -114}, within: "100mi"}}) # or 160km
|
954
954
|
```
|
955
955
|
|
956
956
|
Bounded by a box
|
957
957
|
|
958
958
|
```ruby
|
959
|
-
Restaurant.search
|
959
|
+
Restaurant.search("sushi", where: {location: {top_left: {lat: 38, lon: -123}, bottom_right: {lat: 37, lon: -122}}})
|
960
960
|
```
|
961
961
|
|
962
962
|
**Note:** `top_right` and `bottom_left` also work
|
@@ -964,7 +964,7 @@ Restaurant.search "sushi", where: {location: {top_left: {lat: 38, lon: -123}, bo
|
|
964
964
|
Bounded by a polygon
|
965
965
|
|
966
966
|
```ruby
|
967
|
-
Restaurant.search
|
967
|
+
Restaurant.search("dessert", where: {location: {geo_polygon: {points: [{lat: 38, lon: -123}, {lat: 39, lon: -123}, {lat: 37, lon: 122}]}}})
|
968
968
|
```
|
969
969
|
|
970
970
|
### Boost By Distance
|
@@ -972,13 +972,13 @@ Restaurant.search "dessert", where: {location: {geo_polygon: {points: [{lat: 38,
|
|
972
972
|
Boost results by distance - closer results are boosted more
|
973
973
|
|
974
974
|
```ruby
|
975
|
-
Restaurant.search
|
975
|
+
Restaurant.search("noodles", boost_by_distance: {location: {origin: {lat: 37, lon: -122}}})
|
976
976
|
```
|
977
977
|
|
978
978
|
Also supports [additional options](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#function-decay)
|
979
979
|
|
980
980
|
```ruby
|
981
|
-
Restaurant.search
|
981
|
+
Restaurant.search("wings", boost_by_distance: {location: {origin: {lat: 37, lon: -122}, function: "linear", scale: "30mi", decay: 0.5}})
|
982
982
|
```
|
983
983
|
|
984
984
|
### Geo Shapes
|
@@ -1005,19 +1005,19 @@ See the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsea
|
|
1005
1005
|
Find shapes intersecting with the query shape
|
1006
1006
|
|
1007
1007
|
```ruby
|
1008
|
-
Restaurant.search
|
1008
|
+
Restaurant.search("soup", where: {bounds: {geo_shape: {type: "polygon", coordinates: [[{lat: 38, lon: -123}, ...]]}}})
|
1009
1009
|
```
|
1010
1010
|
|
1011
1011
|
Falling entirely within the query shape
|
1012
1012
|
|
1013
1013
|
```ruby
|
1014
|
-
Restaurant.search
|
1014
|
+
Restaurant.search("salad", where: {bounds: {geo_shape: {type: "circle", relation: "within", coordinates: [{lat: 38, lon: -123}], radius: "1km"}}})
|
1015
1015
|
```
|
1016
1016
|
|
1017
1017
|
Not touching the query shape
|
1018
1018
|
|
1019
1019
|
```ruby
|
1020
|
-
Restaurant.search
|
1020
|
+
Restaurant.search("burger", where: {bounds: {geo_shape: {type: "envelope", relation: "disjoint", coordinates: [{lat: 38, lon: -123}, {lat: 37, lon: -122}]}}})
|
1021
1021
|
```
|
1022
1022
|
|
1023
1023
|
## Inheritance
|
@@ -1047,9 +1047,9 @@ Dog.reindex # equivalent, all animals reindexed
|
|
1047
1047
|
And to search, use:
|
1048
1048
|
|
1049
1049
|
```ruby
|
1050
|
-
Animal.search
|
1051
|
-
Dog.search
|
1052
|
-
Animal.search
|
1050
|
+
Animal.search("*") # all animals
|
1051
|
+
Dog.search("*") # just dogs
|
1052
|
+
Animal.search("*", type: [Dog, Cat]) # just cats and dogs
|
1053
1053
|
```
|
1054
1054
|
|
1055
1055
|
**Notes:**
|
@@ -1057,7 +1057,7 @@ Animal.search "*", type: [Dog, Cat] # just cats and dogs
|
|
1057
1057
|
1. The `suggest` option retrieves suggestions from the parent at the moment.
|
1058
1058
|
|
1059
1059
|
```ruby
|
1060
|
-
Dog.search
|
1060
|
+
Dog.search("airbudd", suggest: true) # suggestions for all animals
|
1061
1061
|
```
|
1062
1062
|
2. This relies on a `type` field that is automatically added to the indexed document. Be wary of defining your own `type` field in `search_data`, as it will take precedence.
|
1063
1063
|
|
@@ -1380,6 +1380,8 @@ Create an initializer with multiple hosts:
|
|
1380
1380
|
|
1381
1381
|
```ruby
|
1382
1382
|
ENV["ELASTICSEARCH_URL"] = "https://user:password@host1,https://user:password@host2"
|
1383
|
+
# or
|
1384
|
+
ENV["OPENSEARCH_URL"] = "https://user:password@host1,https://user:password@host2"
|
1383
1385
|
```
|
1384
1386
|
|
1385
1387
|
See [elastic-transport](https://github.com/elastic/elastic-transport-ruby) or [opensearch-transport](https://github.com/opensearch-project/opensearch-ruby/tree/main/opensearch-transport) for a complete list of options.
|
@@ -1562,7 +1564,7 @@ end
|
|
1562
1564
|
Reindex and search with:
|
1563
1565
|
|
1564
1566
|
```ruby
|
1565
|
-
Business.search
|
1567
|
+
Business.search("ice cream", routing: params[:city_id])
|
1566
1568
|
```
|
1567
1569
|
|
1568
1570
|
### Partial Reindexing
|
@@ -1685,7 +1687,7 @@ end
|
|
1685
1687
|
And use the `body` option to search:
|
1686
1688
|
|
1687
1689
|
```ruby
|
1688
|
-
products = Product.search
|
1690
|
+
products = Product.search(body: {query: {match: {name: "milk"}}})
|
1689
1691
|
```
|
1690
1692
|
|
1691
1693
|
View the response with:
|
@@ -1697,14 +1699,14 @@ products.response
|
|
1697
1699
|
To modify the query generated by Searchkick, use:
|
1698
1700
|
|
1699
1701
|
```ruby
|
1700
|
-
products = Product.search
|
1702
|
+
products = Product.search("milk", body_options: {min_score: 1})
|
1701
1703
|
```
|
1702
1704
|
|
1703
1705
|
or
|
1704
1706
|
|
1705
1707
|
```ruby
|
1706
1708
|
products =
|
1707
|
-
Product.search
|
1709
|
+
Product.search("apples") do |body|
|
1708
1710
|
body[:min_score] = 1
|
1709
1711
|
end
|
1710
1712
|
```
|
@@ -1736,7 +1738,7 @@ Then use `products` and `coupons` as typical results.
|
|
1736
1738
|
Search across multiple models with:
|
1737
1739
|
|
1738
1740
|
```ruby
|
1739
|
-
Searchkick.search
|
1741
|
+
Searchkick.search("milk", models: [Product, Category])
|
1740
1742
|
```
|
1741
1743
|
|
1742
1744
|
Boost specific models with:
|
@@ -1762,7 +1764,7 @@ end
|
|
1762
1764
|
You can also scroll batches manually.
|
1763
1765
|
|
1764
1766
|
```ruby
|
1765
|
-
products = Product.search
|
1767
|
+
products = Product.search("*", scroll: "1m")
|
1766
1768
|
while products.any?
|
1767
1769
|
# process batch ...
|
1768
1770
|
|
@@ -1793,7 +1795,7 @@ Product.search("pears", body_options: {track_total_hits: true})
|
|
1793
1795
|
To query nested data, use dot notation.
|
1794
1796
|
|
1795
1797
|
```ruby
|
1796
|
-
|
1798
|
+
Product.search("san", fields: ["store.city"], where: {"store.zip_code" => 12345})
|
1797
1799
|
```
|
1798
1800
|
|
1799
1801
|
## Reference
|
@@ -1923,7 +1925,7 @@ Searchkick.queue_name = :search_reindex
|
|
1923
1925
|
Eager load associations
|
1924
1926
|
|
1925
1927
|
```ruby
|
1926
|
-
Product.search
|
1928
|
+
Product.search("milk", includes: [:brand, :stores])
|
1927
1929
|
```
|
1928
1930
|
|
1929
1931
|
Eager load different associations by model
|
@@ -1935,7 +1937,7 @@ Searchkick.search("*", models: [Product, Store], model_includes: {Product => [:
|
|
1935
1937
|
Run additional scopes on results
|
1936
1938
|
|
1937
1939
|
```ruby
|
1938
|
-
Product.search
|
1940
|
+
Product.search("milk", scope_results: ->(r) { r.with_attached_images })
|
1939
1941
|
```
|
1940
1942
|
|
1941
1943
|
Specify default fields to search
|
@@ -2031,13 +2033,13 @@ rake searchkick:reindex:all
|
|
2031
2033
|
Turn on misspellings after a certain number of characters
|
2032
2034
|
|
2033
2035
|
```ruby
|
2034
|
-
Product.search
|
2036
|
+
Product.search("api", misspellings: {prefix_length: 2}) # api, apt, no ahi
|
2035
2037
|
```
|
2036
2038
|
|
2037
2039
|
**Note:** With this option, if the query length is the same as `prefix_length`, misspellings are turned off with Elasticsearch 7 and OpenSearch
|
2038
2040
|
|
2039
2041
|
```ruby
|
2040
|
-
Product.search
|
2042
|
+
Product.search("ah", misspellings: {prefix_length: 2}) # ah, no aha
|
2041
2043
|
```
|
2042
2044
|
|
2043
2045
|
## Gotchas
|
data/lib/searchkick/model.rb
CHANGED
@@ -88,9 +88,9 @@ module Searchkick
|
|
88
88
|
if options[:index_name]
|
89
89
|
options[:index_name]
|
90
90
|
elsif options[:index_prefix].respond_to?(:call)
|
91
|
-
-> { [options[:index_prefix].call, model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_") }
|
91
|
+
-> { [options[:index_prefix].call, searchkick_klass.model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_") }
|
92
92
|
else
|
93
|
-
[options.key?(:index_prefix) ? options[:index_prefix] : Searchkick.index_prefix, model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_")
|
93
|
+
[options.key?(:index_prefix) ? options[:index_prefix] : Searchkick.index_prefix, searchkick_klass.model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_")
|
94
94
|
end
|
95
95
|
end
|
96
96
|
end
|
data/lib/searchkick/relation.rb
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
module Searchkick
|
2
2
|
class Relation
|
3
|
+
NO_DEFAULT_VALUE = Object.new
|
4
|
+
|
3
5
|
# note: modifying body directly is not supported
|
4
6
|
# and has no impact on query after being executed
|
5
7
|
# TODO freeze body object?
|
6
|
-
delegate :body, :params, to:
|
8
|
+
delegate :body, :params, to: :query
|
7
9
|
delegate_missing_to :private_execute
|
8
10
|
|
9
11
|
def initialize(model, term = "*", **options)
|
10
|
-
@
|
12
|
+
@model = model
|
13
|
+
@term = term
|
14
|
+
@options = options
|
15
|
+
|
16
|
+
# generate query to validate options
|
17
|
+
query
|
11
18
|
end
|
12
19
|
|
13
20
|
# same as Active Record
|
@@ -23,14 +30,83 @@ module Searchkick
|
|
23
30
|
self
|
24
31
|
end
|
25
32
|
|
33
|
+
def limit(value)
|
34
|
+
clone.limit!(value)
|
35
|
+
end
|
36
|
+
|
37
|
+
def limit!(value)
|
38
|
+
check_loaded
|
39
|
+
@options[:limit] = value
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def offset(value = NO_DEFAULT_VALUE)
|
44
|
+
# TODO remove in Searchkick 6
|
45
|
+
if value == NO_DEFAULT_VALUE
|
46
|
+
private_execute.offset
|
47
|
+
else
|
48
|
+
clone.offset!(value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def offset!(value)
|
53
|
+
check_loaded
|
54
|
+
@options[:offset] = value
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def page(value)
|
59
|
+
clone.page!(value)
|
60
|
+
end
|
61
|
+
|
62
|
+
def page!(value)
|
63
|
+
check_loaded
|
64
|
+
@options[:page] = value
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def per_page(value = NO_DEFAULT_VALUE)
|
69
|
+
# TODO remove in Searchkick 6
|
70
|
+
if value == NO_DEFAULT_VALUE
|
71
|
+
private_execute.per_page
|
72
|
+
else
|
73
|
+
clone.per_page!(value)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def per_page!(value)
|
78
|
+
check_loaded
|
79
|
+
@options[:per_page] = value
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
def only(*keys)
|
84
|
+
Relation.new(@model, @term, **@options.slice(*keys))
|
85
|
+
end
|
86
|
+
|
87
|
+
def except(*keys)
|
88
|
+
Relation.new(@model, @term, **@options.except(*keys))
|
89
|
+
end
|
90
|
+
|
91
|
+
def loaded?
|
92
|
+
!@execute.nil?
|
93
|
+
end
|
94
|
+
|
26
95
|
private
|
27
96
|
|
28
97
|
def private_execute
|
29
|
-
@execute ||=
|
98
|
+
@execute ||= query.execute
|
30
99
|
end
|
31
100
|
|
32
101
|
def query
|
33
|
-
@query
|
102
|
+
@query ||= Query.new(@model, @term, **@options)
|
103
|
+
end
|
104
|
+
|
105
|
+
def check_loaded
|
106
|
+
raise Error, "Relation loaded" if loaded?
|
107
|
+
|
108
|
+
# reset query since options will change
|
109
|
+
@query = nil
|
34
110
|
end
|
35
111
|
end
|
36
112
|
end
|
data/lib/searchkick/version.rb
CHANGED
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: 5.0.
|
4
|
+
version: 5.0.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: 2022-
|
11
|
+
date: 2022-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|