From 3df045a3d82f265378048693ada801e867bc680d Mon Sep 17 00:00:00 2001 From: Andrew Kane Date: Sat, 28 Jan 2017 16:50:19 -0800 Subject: [PATCH] Added experimental support for Cequel - #828 --- lib/searchkick.rb | 2 ++ lib/searchkick/model.rb | 6 ++++++ lib/searchkick/reindex_v2_job.rb | 3 ++- test/aggs_test.rb | 4 ++-- test/boost_test.rb | 2 ++ test/errors_test.rb | 4 ++-- test/gemfiles/cequel.gemfile | 8 ++++++++ test/inheritance_test.rb | 5 +++++ test/match_test.rb | 1 + test/model_test.rb | 2 +- test/order_test.rb | 2 ++ test/records_test.rb | 2 ++ test/reindex_test.rb | 4 ++-- test/test_helper.rb | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/where_test.rb | 25 +++++++++++++++++++------ 15 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 test/gemfiles/cequel.gemfile diff --git a/lib/searchkick.rb b/lib/searchkick.rb index c378d86..7ccd726 100644 --- a/lib/searchkick.rb +++ b/lib/searchkick.rb @@ -169,6 +169,8 @@ module Searchkick elsif records.respond_to?(:unscoped) && :id.respond_to?(:in) # Nobrainer records.unscoped.where(:id.in => ids) + elsif records.respond_to?(:key_column_names) + records.where(records.key_column_names.first => ids) end raise Searchkick::Error, "Not sure how to load records" if !records diff --git a/lib/searchkick/model.rb b/lib/searchkick/model.rb index 882bbc8..83e7a33 100644 --- a/lib/searchkick/model.rb +++ b/lib/searchkick/model.rb @@ -144,6 +144,12 @@ module Searchkick def should_index? true end unless method_defined?(:should_index?) + + if defined?(Cequel) && self < Cequel::Record && !method_defined?(:destroyed?) + def destroyed? + transient? + end + end end end end diff --git a/lib/searchkick/reindex_v2_job.rb b/lib/searchkick/reindex_v2_job.rb index 25cdbe7..942571b 100644 --- a/lib/searchkick/reindex_v2_job.rb +++ b/lib/searchkick/reindex_v2_job.rb @@ -3,7 +3,8 @@ module Searchkick RECORD_NOT_FOUND_CLASSES = [ "ActiveRecord::RecordNotFound", "Mongoid::Errors::DocumentNotFound", - "NoBrainer::Error::DocumentNotFound" + "NoBrainer::Error::DocumentNotFound", + "Cequel::Record::RecordNotFound" ] queue_as :searchkick diff --git a/test/aggs_test.rb b/test/aggs_test.rb index dae7283..f1911de 100644 --- a/test/aggs_test.rb +++ b/test/aggs_test.rb @@ -6,8 +6,8 @@ class AggsTest < Minitest::Test store [ {name: "Product Show", latitude: 37.7833, longitude: 12.4167, store_id: 1, in_stock: true, color: "blue", price: 21, created_at: 2.days.ago}, {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}, - {name: "Product B", latitude: 43.9333, longitude: -122.4667, store_id: 2, in_stock: false, color: "red", price: 5}, - {name: "Foo", latitude: 43.9333, longitude: 12.4667, store_id: 3, in_stock: false, color: "yellow", price: 15} + {name: "Product B", latitude: 43.9333, longitude: -122.4667, store_id: 2, in_stock: false, color: "red", price: 5, created_at: Time.now}, + {name: "Foo", latitude: 43.9333, longitude: 12.4667, store_id: 3, in_stock: false, color: "yellow", price: 15, created_at: Time.now} ] end diff --git a/test/boost_test.rb b/test/boost_test.rb index b7a1418..0a342a4 100644 --- a/test/boost_test.rb +++ b/test/boost_test.rb @@ -157,6 +157,8 @@ class BoostTest < Minitest::Test end def test_boost_by_indices + skip if cequel? + store_names ["Rex"], Animal store_names ["Rexx"], Product diff --git a/test/errors_test.rb b/test/errors_test.rb index 238d4c3..74615a4 100644 --- a/test/errors_test.rb +++ b/test/errors_test.rb @@ -2,8 +2,8 @@ require_relative "test_helper" class ErrorsTest < Minitest::Test def test_bulk_import_raises_error - valid_dog = Dog.new(name: "2016-01-02") - invalid_dog = Dog.new(name: "Ol' One-Leg") + valid_dog = Product.new(name: "2016-01-02") + invalid_dog = Product.new(name: "Ol' One-Leg") index = Searchkick::Index.new "dogs", mappings: { dog: { properties: { diff --git a/test/gemfiles/cequel.gemfile b/test/gemfiles/cequel.gemfile new file mode 100644 index 0000000..c16a665 --- /dev/null +++ b/test/gemfiles/cequel.gemfile @@ -0,0 +1,8 @@ +source 'https://rubygems.org' + +# Specify your gem's dependencies in searchkick.gemspec +gemspec path: "../../" + +gem "cequel" +gem "activejob" +gem "redis" diff --git a/test/inheritance_test.rb b/test/inheritance_test.rb index c18a188..a0d1d9a 100644 --- a/test/inheritance_test.rb +++ b/test/inheritance_test.rb @@ -1,6 +1,11 @@ require_relative "test_helper" class InheritanceTest < Minitest::Test + def setup + skip if defined?(Cequel) + super + end + def test_child_reindex store_names ["Max"], Cat assert Dog.reindex diff --git a/test/match_test.rb b/test/match_test.rb index 81927c2..bfeb4e5 100644 --- a/test/match_test.rb +++ b/test/match_test.rb @@ -184,6 +184,7 @@ class MatchTest < Minitest::Test end def test_no_arguments + store_names [] assert_equal [], Product.search.to_a end diff --git a/test/model_test.rb b/test/model_test.rb index 44b7390..f25f117 100644 --- a/test/model_test.rb +++ b/test/model_test.rb @@ -37,6 +37,6 @@ class ModelTest < Minitest::Test def test_multiple_models store_names ["Product A"] store_names ["Product B"], Speaker - assert_equal Product.all + Speaker.all, Searchkick.search("product", index_name: [Product, Speaker], fields: [:name], order: "name").to_a + assert_equal Product.all.to_a + Speaker.all.to_a, Searchkick.search("product", index_name: [Product, Speaker], fields: [:name], order: "name").to_a end end diff --git a/test/order_test.rb b/test/order_test.rb index 80ddcf2..13fd94c 100644 --- a/test/order_test.rb +++ b/test/order_test.rb @@ -12,6 +12,8 @@ class OrderTest < Minitest::Test end def test_order_id + skip if cequel? + store_names ["Product A", "Product B"] product_a = Product.where(name: "Product A").first product_b = Product.where(name: "Product B").first diff --git a/test/records_test.rb b/test/records_test.rb index d18ade3..d779a97 100644 --- a/test/records_test.rb +++ b/test/records_test.rb @@ -2,6 +2,8 @@ require_relative "test_helper" class RecordsTest < Minitest::Test def test_records + skip if cequel? + store_names ["Milk", "Apple"] assert_equal Product.search("milk").records.where(name: "Milk").count, 1 end diff --git a/test/reindex_test.rb b/test/reindex_test.rb index 9c7d931..21d2e9f 100644 --- a/test/reindex_test.rb +++ b/test/reindex_test.rb @@ -2,7 +2,7 @@ require_relative "test_helper" class ReindexTest < Minitest::Test def test_scoped - skip if nobrainer? + skip if nobrainer? || cequel? store_names ["Product A"] Searchkick.callbacks(false) do @@ -13,7 +13,7 @@ class ReindexTest < Minitest::Test end def test_associations - skip if nobrainer? + skip if nobrainer? || cequel? store_names ["Product A"] store = Store.create!(name: "Test") diff --git a/test/test_helper.rb b/test/test_helper.rb index fe36fb4..3758ae5 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -45,6 +45,10 @@ def nobrainer? defined?(NoBrainer) end +def cequel? + defined?(Cequel) +end + if defined?(Mongoid) Mongoid.logger.level = Logger::INFO Mongo::Logger.logger.level = Logger::INFO if defined?(Mongo::Logger) @@ -162,6 +166,87 @@ elsif defined?(NoBrainer) class Cat < Animal end +elsif defined?(Cequel) + cequel = + Cequel.connect( + host: "127.0.0.1", + port: 9042, + keyspace: "searchkick_test", + default_consistency: :all + ) + cequel.schema.drop! if cequel.schema.exists? + cequel.schema.create! + Cequel::Record.connection = cequel + + class Product + include Cequel::Record + + key :id, :uuid, auto: true + column :name, :text, index: true + column :store_id, :int + column :in_stock, :boolean + column :backordered, :boolean + column :orders_count, :int + column :found_rate, :decimal + column :price, :int + column :color, :text + column :latitude, :decimal + column :longitude, :decimal + column :description, :text + column :alt_description, :text + column :created_at, :timestamp + end + + class Store + include Cequel::Record + + key :id, :timeuuid, auto: true + column :name, :text + + # has issue with id serialization + def search_data + { + name: name + } + end + end + + class Region + include Cequel::Record + + key :id, :timeuuid, auto: true + column :name, :text + column :text, :text + end + + class Speaker + include Cequel::Record + + key :id, :timeuuid, auto: true + column :name, :text + end + + class Animal + include Cequel::Record + + key :id, :timeuuid, auto: true + column :name, :text + + # has issue with id serialization + def search_data + { + name: name + } + end + end + + class Dog < Animal + end + + class Cat < Animal + end + + [Product, Store, Region, Speaker, Animal].each(&:synchronize_schema) else require "active_record" diff --git a/test/where_test.rb b/test/where_test.rb index 04e4611..378e455 100644 --- a/test/where_test.rb +++ b/test/where_test.rb @@ -10,16 +10,22 @@ class WhereTest < Minitest::Test {name: "Product D", store_id: 4, in_stock: false, backordered: false, created_at: now - 3, orders_count: 1} ] assert_search "product", ["Product A", "Product B"], where: {in_stock: true} - # date - assert_search "product", ["Product A"], where: {created_at: {gt: now - 1}} - assert_search "product", ["Product A", "Product B"], where: {created_at: {gte: now - 1}} - assert_search "product", ["Product D"], where: {created_at: {lt: now - 2}} - assert_search "product", ["Product C", "Product D"], where: {created_at: {lte: now - 2}} + + # due to precision + unless cequel? + # date + assert_search "product", ["Product A"], where: {created_at: {gt: now - 1}} + assert_search "product", ["Product A", "Product B"], where: {created_at: {gte: now - 1}} + assert_search "product", ["Product D"], where: {created_at: {lt: now - 2}} + assert_search "product", ["Product C", "Product D"], where: {created_at: {lte: now - 2}} + end + # integer assert_search "product", ["Product A"], where: {store_id: {lt: 2}} assert_search "product", ["Product A", "Product B"], where: {store_id: {lte: 2}} assert_search "product", ["Product D"], where: {store_id: {gt: 3}} assert_search "product", ["Product C", "Product D"], where: {store_id: {gte: 3}} + # range assert_search "product", ["Product A", "Product B"], where: {store_id: 1..2} assert_search "product", ["Product A"], where: {store_id: 1...2} @@ -27,23 +33,30 @@ class WhereTest < Minitest::Test assert_search "product", ["Product B", "Product C", "Product D"], where: {store_id: {not: 1}} assert_search "product", ["Product C", "Product D"], where: {store_id: {not: [1, 2]}} assert_search "product", ["Product A"], where: {user_ids: {lte: 2, gte: 2}} + # or assert_search "product", ["Product A", "Product B", "Product C"], where: {or: [[{in_stock: true}, {store_id: 3}]]} assert_search "product", ["Product A", "Product B", "Product C"], where: {or: [[{orders_count: [2, 4]}, {store_id: [1, 2]}]]} assert_search "product", ["Product A", "Product D"], where: {or: [[{orders_count: 1}, {created_at: {gte: now - 1}, backordered: true}]]} + # _or assert_search "product", ["Product A", "Product B", "Product C"], where: {_or: [{in_stock: true}, {store_id: 3}]} assert_search "product", ["Product A", "Product B", "Product C"], where: {_or: [{orders_count: [2, 4]}, {store_id: [1, 2]}]} assert_search "product", ["Product A", "Product D"], where: {_or: [{orders_count: 1}, {created_at: {gte: now - 1}, backordered: true}]} + # _and assert_search "product", ["Product A"], where: {_and: [{in_stock: true}, {backordered: true}]} + # _not assert_search "product", ["Product B", "Product C"], where: {_not: {_or: [{orders_count: 1}, {created_at: {gte: now - 1}, backordered: true}]}} + # all assert_search "product", ["Product A", "Product C"], where: {user_ids: {all: [1, 3]}} assert_search "product", [], where: {user_ids: {all: [1, 2, 3, 4]}} + # any / nested terms assert_search "product", ["Product B", "Product C"], where: {user_ids: {not: [2], in: [1, 3]}} + # not / exists assert_search "product", ["Product D"], where: {user_ids: nil} assert_search "product", ["Product A", "Product B", "Product C"], where: {user_ids: {not: nil}} @@ -78,7 +91,7 @@ class WhereTest < Minitest::Test def test_where_id store_names ["Product A"] - product = Product.last + product = Product.first assert_search "product", ["Product A"], where: {id: product.id.to_s} end -- libgit2 0.21.0