[英]Elasticsearch rails/ Elasticsearch model search model association
我有一个名为Movie
的模型,如下所示:
class Movie < ActiveRecord::Base
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
has_many :actors, after_add: [ lambda {|a,c| a.__elasticsearch__.index_document}],
after_remove: [ lambda {|a,c| a.__elasticsearch__.index_document}]
settings index: {number_of_shards: 1} do
mappings dynamic: 'false' do
indexes :title, analyzer: 'snowball', boost: 100
indexes :actors
end
end
def as_indexed_json(options={})
self.as_json(
include: {
actors: { only: :name}
}
)
end
end
当我做Movie.first.as_indexed_json
,我得到:
{"id"=>6, "title"=>"Back to the Future ",
"created_at"=>Wed, 03 Dec 2014 22:21:24 UTC +00:00,
"updated_at"=>Fri, 12 Dec 2014 23:40:03 UTC +00:00,
"actors"=>[{"name"=>"Michael J Fox"}, {"name"=>"Christopher Lloyd"},
{"name"=>"Lea Thompson"}]}
但是当我做Movie.search("Christopher Lloyd").records.first
我得到: => nil
。
我可以对索引进行哪些更改来搜索与搜索到的actor相关联的电影?
您可以尝试将方法搜索添加到您的模型,如下所示:
class Movie < ActiveRecord::Base
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
# ...
def self.search(query, options = {})
es_options =
{
query: {
query_string: {
query: query,
default_operator: 'AND',
}
},
sort: '_score',
}.merge!(options)
__elasticsearch__.search(es_options)
end
# ...
end
以下是方法搜索的一些示例: http : //www.sitepoint.com/full-text-search-rails-elasticsearch/
现在,您可以搜索所有索引字段。
我使用filtering query
来解决这个问题,首先我创建了一个名为searchable.rb
的ActiveSupport::Concern
,关注点如下:
module Searchable
extend ActiveSupport::Concern
included do
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
index_name [Rails.application.engine_name, Rails.env].join('_')
settings index: { number_of_shards: 3, number_of_replicas: 0} do
mapping do
indexes :title, type: 'multi_field' do
indexes :title, analyzer: 'snowball'
indexes :tokenized, analyzer: 'simple'
end
indexes :actors, analyzer: 'keyword'
end
def as_indexed_json(options={})
hash = self.as_json()
hash['actors'] = self.actors.map(&:name)
hash
end
def self.search(query, options={})
__set_filters = lambda do |key, f|
@search_definition[:post_filter][:and] ||= []
@search_definition[:post_filter][:and] |= [f]
end
@search_definition = {
query: {},
highlight: {
pre_tags: ['<em class="label label-highlight">'],
post_tags: ['</em>'],
fields: {
title: {number_of_fragments: 0}
}
},
post_filter: {},
aggregations: {
actors: {
filter: {bool: {must: [match_all: {}]}},
aggregations: {actors: {terms: {field: 'actors'}}}
}
}
}
unless query.blank?
@search_definition[:query] = {
bool: {
should: [
{
multi_match: {
query: query,
fields: ['title^10'],
operator: 'and'
}
}
]
}
}
else
@search_definition[:query] = { match_all: {} }
@search_definition[:sort] = {created_at: 'desc'}
end
if options[:actor]
f = {term: { actors: options[:taxon]}}
end
if options[:sort]
@search_definition[:sort] = { options[:sort] => 'desc'}
@search_definition[:track_scores] = true
end
__elasticsearch__.search(@search_definition)
end
end
end
我在models/concerns
目录中有上述问题。 在movies.rb
我有:
class Movie < ActiveRecord::Base
include Searchable
end
在movies_controller.rb
我正在搜索index
操作,操作如下所示:
def index
options = {
actor: params[:taxon],
sort: params[:sort]
}
@movies = Movie.search(params[q], options).records
end
现在当我去http://localhost:3000/movies?q=future&actor=Christopher
我得到所有在他们的标题上都有未来一词的唱片,并且有一个名叫Christopher的演员。 你可以有一个以上的过滤器如用expert
的示例应用程序模板,模板在这里找到 。
试试这个
indexes :actors do
indexes :name, type: "string"
end
您需要在search
方法中指定字段,例如:
def self.search query
__elasticsearch__.search(
query: {
multi_match: {
query: query,
fields: %w[title actor.name]
}
}
)
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.