Commit 3df045a3d82f265378048693ada801e867bc680d

Authored by Andrew Kane
1 parent 0a17dd2e

Added experimental support for Cequel - #828

lib/searchkick.rb
... ... @@ -169,6 +169,8 @@ module Searchkick
169 169 elsif records.respond_to?(:unscoped) && :id.respond_to?(:in)
170 170 # Nobrainer
171 171 records.unscoped.where(:id.in => ids)
  172 + elsif records.respond_to?(:key_column_names)
  173 + records.where(records.key_column_names.first => ids)
172 174 end
173 175  
174 176 raise Searchkick::Error, "Not sure how to load records" if !records
... ...
lib/searchkick/model.rb
... ... @@ -144,6 +144,12 @@ module Searchkick
144 144 def should_index?
145 145 true
146 146 end unless method_defined?(:should_index?)
  147 +
  148 + if defined?(Cequel) && self < Cequel::Record && !method_defined?(:destroyed?)
  149 + def destroyed?
  150 + transient?
  151 + end
  152 + end
147 153 end
148 154 end
149 155 end
... ...
lib/searchkick/reindex_v2_job.rb
... ... @@ -3,7 +3,8 @@ module Searchkick
3 3 RECORD_NOT_FOUND_CLASSES = [
4 4 "ActiveRecord::RecordNotFound",
5 5 "Mongoid::Errors::DocumentNotFound",
6   - "NoBrainer::Error::DocumentNotFound"
  6 + "NoBrainer::Error::DocumentNotFound",
  7 + "Cequel::Record::RecordNotFound"
7 8 ]
8 9  
9 10 queue_as :searchkick
... ...
test/aggs_test.rb
... ... @@ -6,8 +6,8 @@ class AggsTest &lt; Minitest::Test
6 6 store [
7 7 {name: "Product Show", latitude: 37.7833, longitude: 12.4167, store_id: 1, in_stock: true, color: "blue", price: 21, created_at: 2.days.ago},
8 8 {name: "Product Hide", latitude: 29.4167, longitude: -98.5000, store_id: 2, in_stock: false, color: "green", price: 25, created_at: 2.days.from_now},
9   - {name: "Product B", latitude: 43.9333, longitude: -122.4667, store_id: 2, in_stock: false, color: "red", price: 5},
10   - {name: "Foo", latitude: 43.9333, longitude: 12.4667, store_id: 3, in_stock: false, color: "yellow", price: 15}
  9 + {name: "Product B", latitude: 43.9333, longitude: -122.4667, store_id: 2, in_stock: false, color: "red", price: 5, created_at: Time.now},
  10 + {name: "Foo", latitude: 43.9333, longitude: 12.4667, store_id: 3, in_stock: false, color: "yellow", price: 15, created_at: Time.now}
11 11 ]
12 12 end
13 13  
... ...
test/boost_test.rb
... ... @@ -157,6 +157,8 @@ class BoostTest &lt; Minitest::Test
157 157 end
158 158  
159 159 def test_boost_by_indices
  160 + skip if cequel?
  161 +
160 162 store_names ["Rex"], Animal
161 163 store_names ["Rexx"], Product
162 164  
... ...
test/errors_test.rb
... ... @@ -2,8 +2,8 @@ require_relative &quot;test_helper&quot;
2 2  
3 3 class ErrorsTest < Minitest::Test
4 4 def test_bulk_import_raises_error
5   - valid_dog = Dog.new(name: "2016-01-02")
6   - invalid_dog = Dog.new(name: "Ol' One-Leg")
  5 + valid_dog = Product.new(name: "2016-01-02")
  6 + invalid_dog = Product.new(name: "Ol' One-Leg")
7 7 index = Searchkick::Index.new "dogs", mappings: {
8 8 dog: {
9 9 properties: {
... ...
test/gemfiles/cequel.gemfile 0 โ†’ 100644
... ... @@ -0,0 +1,8 @@
  1 +source 'https://rubygems.org'
  2 +
  3 +# Specify your gem's dependencies in searchkick.gemspec
  4 +gemspec path: "../../"
  5 +
  6 +gem "cequel"
  7 +gem "activejob"
  8 +gem "redis"
... ...
test/inheritance_test.rb
1 1 require_relative "test_helper"
2 2  
3 3 class InheritanceTest < Minitest::Test
  4 + def setup
  5 + skip if defined?(Cequel)
  6 + super
  7 + end
  8 +
4 9 def test_child_reindex
5 10 store_names ["Max"], Cat
6 11 assert Dog.reindex
... ...
test/match_test.rb
... ... @@ -184,6 +184,7 @@ class MatchTest &lt; Minitest::Test
184 184 end
185 185  
186 186 def test_no_arguments
  187 + store_names []
187 188 assert_equal [], Product.search.to_a
188 189 end
189 190  
... ...
test/model_test.rb
... ... @@ -37,6 +37,6 @@ class ModelTest &lt; Minitest::Test
37 37 def test_multiple_models
38 38 store_names ["Product A"]
39 39 store_names ["Product B"], Speaker
40   - assert_equal Product.all + Speaker.all, Searchkick.search("product", index_name: [Product, Speaker], fields: [:name], order: "name").to_a
  40 + assert_equal Product.all.to_a + Speaker.all.to_a, Searchkick.search("product", index_name: [Product, Speaker], fields: [:name], order: "name").to_a
41 41 end
42 42 end
... ...
test/order_test.rb
... ... @@ -12,6 +12,8 @@ class OrderTest &lt; Minitest::Test
12 12 end
13 13  
14 14 def test_order_id
  15 + skip if cequel?
  16 +
15 17 store_names ["Product A", "Product B"]
16 18 product_a = Product.where(name: "Product A").first
17 19 product_b = Product.where(name: "Product B").first
... ...
test/records_test.rb
... ... @@ -2,6 +2,8 @@ require_relative &quot;test_helper&quot;
2 2  
3 3 class RecordsTest < Minitest::Test
4 4 def test_records
  5 + skip if cequel?
  6 +
5 7 store_names ["Milk", "Apple"]
6 8 assert_equal Product.search("milk").records.where(name: "Milk").count, 1
7 9 end
... ...
test/reindex_test.rb
... ... @@ -2,7 +2,7 @@ require_relative &quot;test_helper&quot;
2 2  
3 3 class ReindexTest < Minitest::Test
4 4 def test_scoped
5   - skip if nobrainer?
  5 + skip if nobrainer? || cequel?
6 6  
7 7 store_names ["Product A"]
8 8 Searchkick.callbacks(false) do
... ... @@ -13,7 +13,7 @@ class ReindexTest &lt; Minitest::Test
13 13 end
14 14  
15 15 def test_associations
16   - skip if nobrainer?
  16 + skip if nobrainer? || cequel?
17 17  
18 18 store_names ["Product A"]
19 19 store = Store.create!(name: "Test")
... ...
test/test_helper.rb
... ... @@ -45,6 +45,10 @@ def nobrainer?
45 45 defined?(NoBrainer)
46 46 end
47 47  
  48 +def cequel?
  49 + defined?(Cequel)
  50 +end
  51 +
48 52 if defined?(Mongoid)
49 53 Mongoid.logger.level = Logger::INFO
50 54 Mongo::Logger.logger.level = Logger::INFO if defined?(Mongo::Logger)
... ... @@ -162,6 +166,87 @@ elsif defined?(NoBrainer)
162 166  
163 167 class Cat < Animal
164 168 end
  169 +elsif defined?(Cequel)
  170 + cequel =
  171 + Cequel.connect(
  172 + host: "127.0.0.1",
  173 + port: 9042,
  174 + keyspace: "searchkick_test",
  175 + default_consistency: :all
  176 + )
  177 + cequel.schema.drop! if cequel.schema.exists?
  178 + cequel.schema.create!
  179 + Cequel::Record.connection = cequel
  180 +
  181 + class Product
  182 + include Cequel::Record
  183 +
  184 + key :id, :uuid, auto: true
  185 + column :name, :text, index: true
  186 + column :store_id, :int
  187 + column :in_stock, :boolean
  188 + column :backordered, :boolean
  189 + column :orders_count, :int
  190 + column :found_rate, :decimal
  191 + column :price, :int
  192 + column :color, :text
  193 + column :latitude, :decimal
  194 + column :longitude, :decimal
  195 + column :description, :text
  196 + column :alt_description, :text
  197 + column :created_at, :timestamp
  198 + end
  199 +
  200 + class Store
  201 + include Cequel::Record
  202 +
  203 + key :id, :timeuuid, auto: true
  204 + column :name, :text
  205 +
  206 + # has issue with id serialization
  207 + def search_data
  208 + {
  209 + name: name
  210 + }
  211 + end
  212 + end
  213 +
  214 + class Region
  215 + include Cequel::Record
  216 +
  217 + key :id, :timeuuid, auto: true
  218 + column :name, :text
  219 + column :text, :text
  220 + end
  221 +
  222 + class Speaker
  223 + include Cequel::Record
  224 +
  225 + key :id, :timeuuid, auto: true
  226 + column :name, :text
  227 + end
  228 +
  229 + class Animal
  230 + include Cequel::Record
  231 +
  232 + key :id, :timeuuid, auto: true
  233 + column :name, :text
  234 +
  235 + # has issue with id serialization
  236 + def search_data
  237 + {
  238 + name: name
  239 + }
  240 + end
  241 + end
  242 +
  243 + class Dog < Animal
  244 + end
  245 +
  246 + class Cat < Animal
  247 + end
  248 +
  249 + [Product, Store, Region, Speaker, Animal].each(&:synchronize_schema)
165 250 else
166 251 require "active_record"
167 252  
... ...
test/where_test.rb
... ... @@ -10,16 +10,22 @@ class WhereTest &lt; Minitest::Test
10 10 {name: "Product D", store_id: 4, in_stock: false, backordered: false, created_at: now - 3, orders_count: 1}
11 11 ]
12 12 assert_search "product", ["Product A", "Product B"], where: {in_stock: true}
13   - # date
14   - assert_search "product", ["Product A"], where: {created_at: {gt: now - 1}}
15   - assert_search "product", ["Product A", "Product B"], where: {created_at: {gte: now - 1}}
16   - assert_search "product", ["Product D"], where: {created_at: {lt: now - 2}}
17   - assert_search "product", ["Product C", "Product D"], where: {created_at: {lte: now - 2}}
  13 +
  14 + # due to precision
  15 + unless cequel?
  16 + # date
  17 + assert_search "product", ["Product A"], where: {created_at: {gt: now - 1}}
  18 + assert_search "product", ["Product A", "Product B"], where: {created_at: {gte: now - 1}}
  19 + assert_search "product", ["Product D"], where: {created_at: {lt: now - 2}}
  20 + assert_search "product", ["Product C", "Product D"], where: {created_at: {lte: now - 2}}
  21 + end
  22 +
18 23 # integer
19 24 assert_search "product", ["Product A"], where: {store_id: {lt: 2}}
20 25 assert_search "product", ["Product A", "Product B"], where: {store_id: {lte: 2}}
21 26 assert_search "product", ["Product D"], where: {store_id: {gt: 3}}
22 27 assert_search "product", ["Product C", "Product D"], where: {store_id: {gte: 3}}
  28 +
23 29 # range
24 30 assert_search "product", ["Product A", "Product B"], where: {store_id: 1..2}
25 31 assert_search "product", ["Product A"], where: {store_id: 1...2}
... ... @@ -27,23 +33,30 @@ class WhereTest &lt; Minitest::Test
27 33 assert_search "product", ["Product B", "Product C", "Product D"], where: {store_id: {not: 1}}
28 34 assert_search "product", ["Product C", "Product D"], where: {store_id: {not: [1, 2]}}
29 35 assert_search "product", ["Product A"], where: {user_ids: {lte: 2, gte: 2}}
  36 +
30 37 # or
31 38 assert_search "product", ["Product A", "Product B", "Product C"], where: {or: [[{in_stock: true}, {store_id: 3}]]}
32 39 assert_search "product", ["Product A", "Product B", "Product C"], where: {or: [[{orders_count: [2, 4]}, {store_id: [1, 2]}]]}
33 40 assert_search "product", ["Product A", "Product D"], where: {or: [[{orders_count: 1}, {created_at: {gte: now - 1}, backordered: true}]]}
  41 +
34 42 # _or
35 43 assert_search "product", ["Product A", "Product B", "Product C"], where: {_or: [{in_stock: true}, {store_id: 3}]}
36 44 assert_search "product", ["Product A", "Product B", "Product C"], where: {_or: [{orders_count: [2, 4]}, {store_id: [1, 2]}]}
37 45 assert_search "product", ["Product A", "Product D"], where: {_or: [{orders_count: 1}, {created_at: {gte: now - 1}, backordered: true}]}
  46 +
38 47 # _and
39 48 assert_search "product", ["Product A"], where: {_and: [{in_stock: true}, {backordered: true}]}
  49 +
40 50 # _not
41 51 assert_search "product", ["Product B", "Product C"], where: {_not: {_or: [{orders_count: 1}, {created_at: {gte: now - 1}, backordered: true}]}}
  52 +
42 53 # all
43 54 assert_search "product", ["Product A", "Product C"], where: {user_ids: {all: [1, 3]}}
44 55 assert_search "product", [], where: {user_ids: {all: [1, 2, 3, 4]}}
  56 +
45 57 # any / nested terms
46 58 assert_search "product", ["Product B", "Product C"], where: {user_ids: {not: [2], in: [1, 3]}}
  59 +
47 60 # not / exists
48 61 assert_search "product", ["Product D"], where: {user_ids: nil}
49 62 assert_search "product", ["Product A", "Product B", "Product C"], where: {user_ids: {not: nil}}
... ... @@ -78,7 +91,7 @@ class WhereTest &lt; Minitest::Test
78 91  
79 92 def test_where_id
80 93 store_names ["Product A"]
81   - product = Product.last
  94 + product = Product.first
82 95 assert_search "product", ["Product A"], where: {id: product.id.to_s}
83 96 end
84 97  
... ...