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

Opt*_*tte 5 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
Run Code Online (Sandbox Code Playgroud)

当我这样做时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"}]}
Run Code Online (Sandbox Code Playgroud)

但是当我Movie.search("Christopher Lloyd").records.first得到时:=> nil.

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

Opt*_*tte 2

我曾经filtering query解决过这个问题,首先我创建了一个ActiveSupport::Concernsearchable.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
Run Code Online (Sandbox Code Playgroud)

我在目录中有上述担忧models/concerns。在movies.rb我有:

class Movie < ActiveRecord::Base
  include Searchable
end
Run Code Online (Sandbox Code Playgroud)

我正在movies_controller.rb搜索该index操作,该操作如下所示:

def index 
  options = {
  actor: params[:taxon],
    sort: params[:sort]
  }
  @movies = Movie.search(params[q], options).records
end 
Run Code Online (Sandbox Code Playgroud)

现在,当我去的时候,http://localhost:3000/movies?q=future&actor=Christopher我得到了所有标题上有“未来”一词的记录,并且有一个名叫克里斯托弗的演员。您可以拥有多个过滤器,如此处找到的expert示例应用程序模板的模板所示。