diff --git a/README.md b/README.md index d886156..4031af7 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ Searchkick supports the complete [Elasticsearch Search API](https://www.elastic. Query like SQL ```ruby -Product.search "apples", where: {in_stock: true}, limit: 10, offset: 50 +Product.search("apples", where: {in_stock: true}, limit: 10, offset: 50) ``` Search specific fields @@ -226,7 +226,7 @@ You can also boost by: Use a `*` for the query. ```ruby -Product.search "*" +Product.search("*") ``` ### Pagination @@ -235,7 +235,7 @@ Plays nicely with kaminari and will_paginate. ```ruby # controller -@products = Product.search "milk", page: params[:page], per_page: 20 +@products = Product.search("milk", page: params[:page], per_page: 20) ``` View with kaminari @@ -255,13 +255,13 @@ View with will_paginate By default, results must match all words in the query. ```ruby -Product.search "fresh honey" # fresh AND honey +Product.search("fresh honey") # fresh AND honey ``` To change this, use: ```ruby -Product.search "fresh honey", operator: "or" # fresh OR honey +Product.search("fresh honey", operator: "or") # fresh OR honey ``` By default, results must match the entire word - `back` will not match `backpack`. You can change this behavior with: @@ -275,7 +275,7 @@ end And to search (after you reindex): ```ruby -Product.search "back", fields: [:name], match: :word_start +Product.search("back", fields: [:name], match: :word_start) ``` Available options are: @@ -297,7 +297,7 @@ The default is `:word`. The most matches will happen with `:word_middle`. To match a field exactly (case-sensitive), use: ```ruby -User.search query, fields: [{email: :exact}, :name] +Product.search(query, fields: [{email: :exact}, :name]) ``` ### Phrase Matches @@ -305,7 +305,7 @@ User.search query, fields: [{email: :exact}, :name] To only match the exact order, use: ```ruby -User.search "fresh honey", match: :phrase +Product.search("fresh honey", match: :phrase) ``` ### Stemming and Language @@ -426,7 +426,7 @@ end Search with: ```ruby -Product.search query, fields: [:name_tagged] +Product.search(query, fields: [:name_tagged]) ``` ### Misspellings @@ -436,13 +436,13 @@ By default, Searchkick handles misspelled queries by returning results with an [ You can change this with: ```ruby -Product.search "zucini", misspellings: {edit_distance: 2} # zucchini +Product.search("zucini", misspellings: {edit_distance: 2}) # zucchini ``` 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. ```ruby -Product.search "zuchini", misspellings: {below: 5} +Product.search("zuchini", misspellings: {below: 5}) ``` 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 Turn off misspellings with: ```ruby -Product.search "zuchini", misspellings: false # no zucchini +Product.search("zuchini", misspellings: false) # no zucchini ``` Specify which fields can include misspellings with: ```ruby -Product.search "zucini", fields: [:name, :color], misspellings: {fields: [:name]} +Product.search("zucini", fields: [:name, :color], misspellings: {fields: [:name]}) ``` > When doing this, you must also specify fields to search @@ -466,7 +466,7 @@ Product.search "zucini", fields: [:name, :color], misspellings: {fields: [:name] If a user searches `butter`, they may also get results for `peanut butter`. To prevent this, use: ```ruby -Product.search "butter", exclude: ["peanut butter"] +Product.search("butter", exclude: ["peanut butter"]) ``` You can map queries and terms to exclude with: @@ -477,7 +477,7 @@ exclude_queries = { "cream" => ["ice cream", "whipped cream"] } -Product.search query, exclude: exclude_queries[query] +Product.search(query, exclude: exclude_queries[query]) ``` You can demote results by boosting by a factor less than one: @@ -499,7 +499,7 @@ gem "gemoji-parser" And use: ```ruby -Product.search "🍨🍰", emoji: true +Product.search("🍨🍰", emoji: true) ``` ## Indexing @@ -651,7 +651,7 @@ end 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. ```ruby -Product.search "apple", track: {user_id: current_user.id} +Product.search("apple", track: {user_id: current_user.id}) ``` [See the docs](https://github.com/ankane/searchjoy) for how to install and use. @@ -709,7 +709,7 @@ end Reindex and search with: ```ruby -Product.search "milk", boost_where: {orderer_ids: current_user.id} +Product.search("milk", boost_where: {orderer_ids: current_user.id}) ``` ## Instant Search / Autocomplete @@ -733,7 +733,7 @@ end Reindex and search with: ```ruby -Movie.search "jurassic pa", fields: [:title], match: :word_start +Movie.search("jurassic pa", fields: [:title], match: :word_start) ``` 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 Reindex and search with: ```ruby -products = Product.search "peantu butta", suggest: true +products = Product.search("peantu butta", suggest: true) products.suggestions # ["peanut butter"] ``` @@ -804,40 +804,40 @@ products.suggestions # ["peanut butter"] ![Aggregations](https://gist.github.com/ankane/b6988db2802aca68a589b31e41b44195/raw/40febe948427e5bc53ec4e5dc248822855fef76f/facets.png) ```ruby -products = Product.search "chuck taylor", aggs: [:product_type, :gender, :brand] +products = Product.search("chuck taylor", aggs: [:product_type, :gender, :brand]) products.aggs ``` By default, `where` conditions apply to aggregations. ```ruby -Product.search "wingtips", where: {color: "brandy"}, aggs: [:size] +Product.search("wingtips", where: {color: "brandy"}, aggs: [:size]) # aggregations for brandy wingtips are returned ``` Change this with: ```ruby -Product.search "wingtips", where: {color: "brandy"}, aggs: [:size], smart_aggs: false +Product.search("wingtips", where: {color: "brandy"}, aggs: [:size], smart_aggs: false) # aggregations for all wingtips are returned ``` Set `where` conditions for each aggregation separately with: ```ruby -Product.search "wingtips", aggs: {size: {where: {color: "brandy"}}} +Product.search("wingtips", aggs: {size: {where: {color: "brandy"}}}) ``` Limit ```ruby -Product.search "apples", aggs: {store_id: {limit: 10}} +Product.search("apples", aggs: {store_id: {limit: 10}}) ``` Order ```ruby -Product.search "wingtips", aggs: {color: {order: {"_key" => "asc"}}} # alphabetically +Product.search("wingtips", aggs: {color: {order: {"_key" => "asc"}}}) # alphabetically ``` [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 ```ruby price_ranges = [{to: 20}, {from: 20, to: 50}, {from: 50}] -Product.search "*", aggs: {price: {ranges: price_ranges}} +Product.search("*", aggs: {price: {ranges: price_ranges}}) ``` Minimum document count ```ruby -Product.search "apples", aggs: {store_id: {min_doc_count: 2}} +Product.search("apples", aggs: {store_id: {min_doc_count: 2}}) ``` Script support ```ruby -Product.search "*", aggs: {color: {script: {source: "'Color: ' + _value"}}} +Product.search("*", aggs: {color: {script: {source: "'Color: ' + _value"}}}) ``` Date histogram ```ruby -Product.search "pear", aggs: {products_per_year: {date_histogram: {field: :created_at, interval: :year}}} +Product.search("pear", aggs: {products_per_year: {date_histogram: {field: :created_at, interval: :year}}}) ``` For other aggregation types, including sub-aggregations, use `body_options`: ```ruby -Product.search "orange", body_options: {aggs: {price: {histogram: {field: :price, interval: 10}}}} +Product.search("orange", body_options: {aggs: {price: {histogram: {field: :price, interval: 10}}}}) ``` ## Highlight @@ -886,7 +886,7 @@ end Highlight the search query in the results. ```ruby -bands = Band.search "cinema", highlight: true +bands = Band.search("cinema", highlight: true) ``` View the highlighted fields with: @@ -900,19 +900,19 @@ end To change the tag, use: ```ruby -Band.search "cinema", highlight: {tag: ""} +Band.search("cinema", highlight: {tag: ""}) ``` To highlight and search different fields, use: ```ruby -Band.search "cinema", fields: [:name], highlight: {fields: [:description]} +Band.search("cinema", fields: [:name], highlight: {fields: [:description]}) ``` By default, the entire field is highlighted. To get small snippets instead, use: ```ruby -bands = Band.search "cinema", highlight: {fragment_size: 20} +bands = Band.search("cinema", highlight: {fragment_size: 20}) bands.with_highlights(multiple: true).each do |band, highlights| highlights[:name].join(" and ") end @@ -921,7 +921,7 @@ end Additional options can be specified for each field: ```ruby -Band.search "cinema", fields: [:name], highlight: {fields: {name: {fragment_size: 200}}} +Band.search("cinema", fields: [:name], highlight: {fields: {name: {fragment_size: 200}}}) ``` 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 Reindex and search with: ```ruby -Restaurant.search "pizza", where: {location: {near: {lat: 37, lon: -114}, within: "100mi"}} # or 160km +Restaurant.search("pizza", where: {location: {near: {lat: 37, lon: -114}, within: "100mi"}}) # or 160km ``` Bounded by a box ```ruby -Restaurant.search "sushi", where: {location: {top_left: {lat: 38, lon: -123}, bottom_right: {lat: 37, lon: -122}}} +Restaurant.search("sushi", where: {location: {top_left: {lat: 38, lon: -123}, bottom_right: {lat: 37, lon: -122}}}) ``` **Note:** `top_right` and `bottom_left` also work @@ -964,7 +964,7 @@ Restaurant.search "sushi", where: {location: {top_left: {lat: 38, lon: -123}, bo Bounded by a polygon ```ruby -Restaurant.search "dessert", where: {location: {geo_polygon: {points: [{lat: 38, lon: -123}, {lat: 39, lon: -123}, {lat: 37, lon: 122}]}}} +Restaurant.search("dessert", where: {location: {geo_polygon: {points: [{lat: 38, lon: -123}, {lat: 39, lon: -123}, {lat: 37, lon: 122}]}}}) ``` ### Boost By Distance @@ -972,13 +972,13 @@ Restaurant.search "dessert", where: {location: {geo_polygon: {points: [{lat: 38, Boost results by distance - closer results are boosted more ```ruby -Restaurant.search "noodles", boost_by_distance: {location: {origin: {lat: 37, lon: -122}}} +Restaurant.search("noodles", boost_by_distance: {location: {origin: {lat: 37, lon: -122}}}) ``` Also supports [additional options](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#function-decay) ```ruby -Restaurant.search "wings", boost_by_distance: {location: {origin: {lat: 37, lon: -122}, function: "linear", scale: "30mi", decay: 0.5}} +Restaurant.search("wings", boost_by_distance: {location: {origin: {lat: 37, lon: -122}, function: "linear", scale: "30mi", decay: 0.5}}) ``` ### Geo Shapes @@ -1005,19 +1005,19 @@ See the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsea Find shapes intersecting with the query shape ```ruby -Restaurant.search "soup", where: {bounds: {geo_shape: {type: "polygon", coordinates: [[{lat: 38, lon: -123}, ...]]}}} +Restaurant.search("soup", where: {bounds: {geo_shape: {type: "polygon", coordinates: [[{lat: 38, lon: -123}, ...]]}}}) ``` Falling entirely within the query shape ```ruby -Restaurant.search "salad", where: {bounds: {geo_shape: {type: "circle", relation: "within", coordinates: [{lat: 38, lon: -123}], radius: "1km"}}} +Restaurant.search("salad", where: {bounds: {geo_shape: {type: "circle", relation: "within", coordinates: [{lat: 38, lon: -123}], radius: "1km"}}}) ``` Not touching the query shape ```ruby -Restaurant.search "burger", where: {bounds: {geo_shape: {type: "envelope", relation: "disjoint", coordinates: [{lat: 38, lon: -123}, {lat: 37, lon: -122}]}}} +Restaurant.search("burger", where: {bounds: {geo_shape: {type: "envelope", relation: "disjoint", coordinates: [{lat: 38, lon: -123}, {lat: 37, lon: -122}]}}}) ``` ## Inheritance @@ -1047,9 +1047,9 @@ Dog.reindex # equivalent, all animals reindexed And to search, use: ```ruby -Animal.search "*" # all animals -Dog.search "*" # just dogs -Animal.search "*", type: [Dog, Cat] # just cats and dogs +Animal.search("*") # all animals +Dog.search("*") # just dogs +Animal.search("*", type: [Dog, Cat]) # just cats and dogs ``` **Notes:** @@ -1057,7 +1057,7 @@ Animal.search "*", type: [Dog, Cat] # just cats and dogs 1. The `suggest` option retrieves suggestions from the parent at the moment. ```ruby - Dog.search "airbudd", suggest: true # suggestions for all animals + Dog.search("airbudd", suggest: true) # suggestions for all animals ``` 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. @@ -1562,7 +1562,7 @@ end Reindex and search with: ```ruby -Business.search "ice cream", routing: params[:city_id] +Business.search("ice cream", routing: params[:city_id]) ``` ### Partial Reindexing @@ -1685,7 +1685,7 @@ end And use the `body` option to search: ```ruby -products = Product.search body: {query: {match: {name: "milk"}}} +products = Product.search(body: {query: {match: {name: "milk"}}}) ``` View the response with: @@ -1697,14 +1697,14 @@ products.response To modify the query generated by Searchkick, use: ```ruby -products = Product.search "milk", body_options: {min_score: 1} +products = Product.search("milk", body_options: {min_score: 1}) ``` or ```ruby products = - Product.search "apples" do |body| + Product.search("apples") do |body| body[:min_score] = 1 end ``` @@ -1736,7 +1736,7 @@ Then use `products` and `coupons` as typical results. Search across multiple models with: ```ruby -Searchkick.search "milk", models: [Product, Category] +Searchkick.search("milk", models: [Product, Category]) ``` Boost specific models with: @@ -1762,7 +1762,7 @@ end You can also scroll batches manually. ```ruby -products = Product.search "*", scroll: "1m" +products = Product.search("*", scroll: "1m") while products.any? # process batch ... @@ -1793,7 +1793,7 @@ Product.search("pears", body_options: {track_total_hits: true}) To query nested data, use dot notation. ```ruby -User.search "san", fields: ["address.city"], where: {"address.zip_code" => 12345} +User.search("san", fields: ["address.city"], where: {"address.zip_code" => 12345}) ``` ## Reference @@ -1923,7 +1923,7 @@ Searchkick.queue_name = :search_reindex Eager load associations ```ruby -Product.search "milk", includes: [:brand, :stores] +Product.search("milk", includes: [:brand, :stores]) ``` Eager load different associations by model @@ -1935,7 +1935,7 @@ Searchkick.search("*", models: [Product, Store], model_includes: {Product => [: Run additional scopes on results ```ruby -Product.search "milk", scope_results: ->(r) { r.with_attached_images } +Product.search("milk", scope_results: ->(r) { r.with_attached_images }) ``` Specify default fields to search @@ -2031,13 +2031,13 @@ rake searchkick:reindex:all Turn on misspellings after a certain number of characters ```ruby -Product.search "api", misspellings: {prefix_length: 2} # api, apt, no ahi +Product.search("api", misspellings: {prefix_length: 2}) # api, apt, no ahi ``` **Note:** With this option, if the query length is the same as `prefix_length`, misspellings are turned off with Elasticsearch 7 and OpenSearch ```ruby -Product.search "ah", misspellings: {prefix_length: 2} # ah, no aha +Product.search("ah", misspellings: {prefix_length: 2}) # ah, no aha ``` ## Gotchas -- libgit2 0.21.0