我对ElasticSearch很陌生,但需要使用它来返回产品列表。请不要包含旧答案或引用已弃用的tire gem的链接。
gemfile
ruby '2.2.0'
gem 'rails', '4.0.3'
gem 'elasticsearch-model', '~> 0.1.6'
gem 'elasticsearch-rails', '~> 0.1.6'
我有几个带关系的模型。下面是包含这些关系的代码。
模型和关系
product.rb 包括 Searchable 模块。
belongs_to :family
belongs_to :collection
has_many :benefits_products
has_many :benefits, :through => :benefits_products
def as_indexed_json(options={})
as_json(
include: {:benefits => { :only => [ :id, :name ] },
:categories => { :only => [ :id, :name ] } }
)
end
collection.rb
include Searchable
has_many :products
def as_indexed_json(options={})
as_json(
include: [:products]
)
end
family.rb
include Searchable
has_many :products
def as_indexed_json(options={})
as_json(
include: [:products]
)
end
benefit.rb
include Searchable
has_many :benefits_products
has_many :products, :through => :benefits_products
def as_indexed_json(options={})
as_json(
include: [:products]
)
end
Serachable.rb 是一个 concern,它包含了 Elastic search 和在所有模型中的回调函数。
module Searchable
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 :id, type: 'long'
indexes :name, type: 'string'
indexes :family_id, type: 'long'
indexes :collection_id, type: 'long'
indexes :created_at, type: 'date'
indexes :updated_at, type: 'date'
indexes :benefits, type: 'nested' do
indexes :id, type: 'long'
indexes :name, type: 'string'
end
indexes :categories, type: 'nested' do
indexes :id, type: 'long'
indexes :name, type: 'string'
end
end
end
def self.search(options={})
__set_filters = lambda do |key, f|
@search_definition[:filter][:and] ||= []
@search_definition[:filter][:and] |= [f]
end
@search_definition = {
query: {
filtered: {
query: {
match_all: {}
}
}
},
filter: {}
}
if options[:benefits]
f = { term: { "benefits.id": options[:benefits] } }
__set_filters.(:collection_id, f)
__set_filters.(:family_id, f)
__set_filters.(:categories, f)
end
def as_indexed_json(options={})
as_json(
include: {:benefits => { :only => [ :id, :name ] },
:categories => { :only => [ :id, :name ] } }
)
end
if options[:categories]
...
end
if options[:collection_id]
...
end
if options[:family_id]
...
end
__elasticsearch__.search(@search_definition)
end
end
end
ElasticSearch
我将破折号分隔的标识符拆分为不同的家族、系列和优点。我能够搜索具有特定家族或系列的产品,并返回正确的结果。我也可以返回一个优点的结果,但它们似乎不准确。同时搜索多个优点会产生奇怪的结果。我希望使用所有字段搜索的“AND”组合,但我的结果似乎不是“AND”或“OR”的结果。所以这让我很困惑。
我需要向Product.search方法传递什么参数才能得到期望的结果?
感谢您提供的任何帮助!
编辑
我现在已经验证了产品上索引的优点。我使用curl -XGET 'http://127.0.0.1:9200/products/_search?pretty=1'
,它产生了一个json响应,看起来像这样:
{
"id":4,
"name":"product name"
"family_id":16
"collection_id":6
"created_at":"2015-04-13T12:49:42.000Z"
"updated_at":"2015-04-13T12:49:42.000Z"
"benefits":[
{"id":2,"name":"my benefit 2"},
{"id":6,"name":"my benefit 6"},
{"id":7,"name":"my benefit 7"}
],
"categories":[
{"id":2,"name":"category 2"}
]}
},
{...}
现在我只需要找出如何在ElasticSearch中搜索具有2、6和7号福利的产品,如果我想要上面的示例产品。 我特别寻找提交给elasticsearch #search方法以获得嵌套“AND”查询结果的语法,嵌套查询设置/映射(以确保我没有遗漏任何内容),以及您可以考虑的任何其他相关信息来解决此问题。