173 lines
6.3 KiB
Ruby
173 lines
6.3 KiB
Ruby
|
require 'test_helper'
|
||
|
require 'active_record'
|
||
|
|
||
|
Mongo.setup!
|
||
|
|
||
|
module Elasticsearch
|
||
|
module Model
|
||
|
class MultipleModelsIntegration < Elasticsearch::Test::IntegrationTestCase
|
||
|
context "Multiple models" do
|
||
|
setup do
|
||
|
ActiveRecord::Schema.define(:version => 1) do
|
||
|
create_table :episodes do |t|
|
||
|
t.string :name
|
||
|
t.datetime :created_at, :default => 'NOW()'
|
||
|
end
|
||
|
|
||
|
create_table :series do |t|
|
||
|
t.string :name
|
||
|
t.datetime :created_at, :default => 'NOW()'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
module ::NameSearch
|
||
|
extend ActiveSupport::Concern
|
||
|
|
||
|
included do
|
||
|
include Elasticsearch::Model
|
||
|
include Elasticsearch::Model::Callbacks
|
||
|
|
||
|
settings index: {number_of_shards: 1, number_of_replicas: 0} do
|
||
|
mapping do
|
||
|
indexes :name, type: 'string', analyzer: 'snowball'
|
||
|
indexes :created_at, type: 'date'
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
class ::Episode < ActiveRecord::Base
|
||
|
include NameSearch
|
||
|
end
|
||
|
|
||
|
class ::Series < ActiveRecord::Base
|
||
|
include NameSearch
|
||
|
end
|
||
|
|
||
|
[::Episode, ::Series].each do |model|
|
||
|
model.delete_all
|
||
|
model.__elasticsearch__.create_index! force: true
|
||
|
model.create name: "The #{model.name}"
|
||
|
model.create name: "A great #{model.name}"
|
||
|
model.create name: "The greatest #{model.name}"
|
||
|
model.__elasticsearch__.refresh_index!
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
should "find matching documents across multiple models" do
|
||
|
response = Elasticsearch::Model.search(%q<"The greatest Episode"^2 OR "The greatest Series">, [Series, Episode])
|
||
|
|
||
|
assert response.any?, "Response should not be empty: #{response.to_a.inspect}"
|
||
|
|
||
|
assert_equal 2, response.results.size
|
||
|
assert_equal 2, response.records.size
|
||
|
|
||
|
assert_instance_of Elasticsearch::Model::Response::Result, response.results.first
|
||
|
assert_instance_of Episode, response.records.first
|
||
|
assert_instance_of Series, response.records.last
|
||
|
|
||
|
assert_equal 'The greatest Episode', response.results[0].name
|
||
|
assert_equal 'The greatest Episode', response.records[0].name
|
||
|
|
||
|
assert_equal 'The greatest Series', response.results[1].name
|
||
|
assert_equal 'The greatest Series', response.records[1].name
|
||
|
end
|
||
|
|
||
|
should "provide access to results" do
|
||
|
response = Elasticsearch::Model.search(%q<"A great Episode"^2 OR "A great Series">, [Series, Episode])
|
||
|
|
||
|
assert_equal 'A great Episode', response.results[0].name
|
||
|
assert_equal true, response.results[0].name?
|
||
|
assert_equal false, response.results[0].boo?
|
||
|
|
||
|
assert_equal 'A great Series', response.results[1].name
|
||
|
assert_equal true, response.results[1].name?
|
||
|
assert_equal false, response.results[1].boo?
|
||
|
end
|
||
|
|
||
|
should "only retrieve records for existing results" do
|
||
|
::Series.find_by_name("The greatest Series").delete
|
||
|
::Series.__elasticsearch__.refresh_index!
|
||
|
response = Elasticsearch::Model.search(%q<"The greatest Episode"^2 OR "The greatest Series">, [Series, Episode])
|
||
|
|
||
|
assert response.any?, "Response should not be empty: #{response.to_a.inspect}"
|
||
|
|
||
|
assert_equal 2, response.results.size
|
||
|
assert_equal 1, response.records.size
|
||
|
|
||
|
assert_instance_of Elasticsearch::Model::Response::Result, response.results.first
|
||
|
assert_instance_of Episode, response.records.first
|
||
|
|
||
|
assert_equal 'The greatest Episode', response.results[0].name
|
||
|
assert_equal 'The greatest Episode', response.records[0].name
|
||
|
end
|
||
|
|
||
|
should "paginate the results" do
|
||
|
response = Elasticsearch::Model.search('series OR episode', [Series, Episode])
|
||
|
|
||
|
assert_equal 3, response.page(1).per(3).results.size
|
||
|
assert_equal 3, response.page(2).per(3).results.size
|
||
|
assert_equal 0, response.page(3).per(3).results.size
|
||
|
end
|
||
|
|
||
|
if Mongo.available?
|
||
|
Mongo.connect_to 'mongoid_collections'
|
||
|
|
||
|
context "Across mongoid models" do
|
||
|
setup do
|
||
|
class ::Image
|
||
|
include Mongoid::Document
|
||
|
include Elasticsearch::Model
|
||
|
include Elasticsearch::Model::Callbacks
|
||
|
|
||
|
field :name, type: String
|
||
|
attr_accessible :name if respond_to? :attr_accessible
|
||
|
|
||
|
settings index: {number_of_shards: 1, number_of_replicas: 0} do
|
||
|
mapping do
|
||
|
indexes :name, type: 'string', analyzer: 'snowball'
|
||
|
indexes :created_at, type: 'date'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def as_indexed_json(options={})
|
||
|
as_json(except: [:_id])
|
||
|
end
|
||
|
end
|
||
|
|
||
|
Image.delete_all
|
||
|
Image.__elasticsearch__.create_index! force: true
|
||
|
Image.create! name: "The Image"
|
||
|
Image.create! name: "A great Image"
|
||
|
Image.create! name: "The greatest Image"
|
||
|
Image.__elasticsearch__.refresh_index!
|
||
|
Image.__elasticsearch__.client.cluster.health wait_for_status: 'yellow'
|
||
|
end
|
||
|
|
||
|
should "find matching documents across multiple models" do
|
||
|
response = Elasticsearch::Model.search(%q<"greatest Episode" OR "greatest Image"^2>, [Episode, Image])
|
||
|
|
||
|
assert response.any?, "Response should not be empty: #{response.to_a.inspect}"
|
||
|
|
||
|
assert_equal 2, response.results.size
|
||
|
assert_equal 2, response.records.size
|
||
|
|
||
|
assert_instance_of Elasticsearch::Model::Response::Result, response.results.first
|
||
|
assert_instance_of Image, response.records.first
|
||
|
assert_instance_of Episode, response.records.last
|
||
|
|
||
|
assert_equal 'The greatest Image', response.results[0].name
|
||
|
assert_equal 'The greatest Image', response.records[0].name
|
||
|
|
||
|
assert_equal 'The greatest Episode', response.results[1].name
|
||
|
assert_equal 'The greatest Episode', response.records[1].name
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|