Commit 7e6d2bc7cab9c2a62ee4e5f99a02887f607dbc1e

Authored by Andrew Kane
1 parent 55cfb407

Added search for similar items

README.md
... ... @@ -284,6 +284,17 @@ Advanced
284 284 Product.search "2% Milk", facets: {store_id: {where: {in_stock: true}}}
285 285 ```
286 286  
  287 +### Similar Items [master]
  288 +
  289 +**Note:** Subject to change before the next gem release
  290 +
  291 +Find similar items.
  292 +
  293 +```ruby
  294 +product = Product.first
  295 +product.similar(fields: ["name"])
  296 +```
  297 +
287 298 ## Deployment
288 299  
289 300 Searchkick uses `ENV["ELASTICSEARCH_URL"]` for the Elasticsearch server. This defaults to `http://localhost:9200`.
... ...
lib/searchkick.rb
... ... @@ -3,6 +3,7 @@ require "searchkick/version"
3 3 require "searchkick/reindex"
4 4 require "searchkick/results"
5 5 require "searchkick/search"
  6 +require "searchkick/similar"
6 7 require "searchkick/model"
7 8 require "searchkick/tasks"
8 9 require "searchkick/logger" if defined?(Rails)
... ...
lib/searchkick/model.rb
... ... @@ -7,6 +7,7 @@ module Searchkick
7 7 class_eval do
8 8 extend Searchkick::Search
9 9 extend Searchkick::Reindex
  10 + include Searchkick::Similar
10 11 include Tire::Model::Search
11 12 include Tire::Model::Callbacks
12 13 tire do
... ...
lib/searchkick/similar.rb 0 → 100644
... ... @@ -0,0 +1,32 @@
  1 +module Searchkick
  2 + module Similar
  3 + def similar(options = {})
  4 + like_text = index.retrieve(document_type, id).to_hash
  5 + .keep_if{|k,v| k[0] != "_" and (!options[:fields] or options[:fields].map(&:to_sym).include?(k)) }
  6 + .values.compact.join(" ")
  7 +
  8 + fields = options[:fields] ? options[:fields].map{|f| "#{f}.analyzed" } : ["_all"]
  9 +
  10 + payload = {
  11 + query: {
  12 + more_like_this: {
  13 + fields: fields,
  14 + like_text: like_text,
  15 + min_doc_freq: 1,
  16 + min_term_freq: 1
  17 + }
  18 + },
  19 + filter: {
  20 + not: {
  21 + term: {
  22 + _id: id
  23 + }
  24 + }
  25 + }
  26 + }
  27 +
  28 + search = Tire::Search::Search.new(index_name, payload: payload)
  29 + Searchkick::Results.new(search.json, search.options)
  30 + end
  31 + end
  32 +end
... ...
test/similar_test.rb 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +require_relative "test_helper"
  2 +
  3 +class TestSimilar < Minitest::Unit::TestCase
  4 +
  5 + def test_fields
  6 + store_names ["1% Organic Milk", "2% Organic Milk", "Popcorn"]
  7 + assert_equal ["2% Organic Milk"], Product.find_by(name: "1% Organic Milk").similar(fields: ["name"]).map(&:name)
  8 + end
  9 +
  10 +end
... ...
test/test_helper.rb
... ... @@ -40,7 +40,8 @@ class Product &lt; ActiveRecord::Base
40 40  
41 41 searchkick \
42 42 settings: {
43   - number_of_shards: 1
  43 + number_of_shards: 1,
  44 + number_of_replicas: 0
44 45 },
45 46 synonyms: [
46 47 ["clorox", "bleach"],
... ...