Elasticsearch rails / Elasticsearch模型搜索模型关联

时间:2014-12-20 16:21:56

标签: ruby-on-rails elasticsearch elasticsearch-model

我有一个名为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

我可以对索引进行哪些更改来搜索与搜索到的演员相关联的电影?

4 个答案:

答案 0 :(得分:1)

您可以尝试将方法搜索添加到您的模型中:

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/

现在,您可以搜索所有索引字段。

答案 1 :(得分:1)

我使用filtering query来解决此问题,首先我创建了一个名为ActiveSupport::Concern的{​​{1}},问题看起来像这样:

searchable.rb

我在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 时,我得到了所有在他们的头衔上都有未来一词的唱片,并且有一个名叫克里斯托弗的演员。您可以拥有多个过滤器,如示例应用程序模板found herehttp://localhost:3000/movies?q=future&actor=Christopher模板所示。

答案 2 :(得分:0)

试试这个

indexes :actors do
 indexes :name, type: "string"
end

答案 3 :(得分:0)

您需要在search方法中指定字段,例如:

def self.search query
  __elasticsearch__.search(
    query: {
      multi_match: {
        query: query,
        fields: %w[title actor.name]
      }
    }
  )
end