6

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

4 に答える 4

2

私はfiltering queryこれを解決するために使用しました。最初にActiveSupport::Concern呼び出されたを作成しました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 

ここで にアクセスするhttp://localhost:3000/movies?q=future&actor=Christopherと、タイトルに「未来」という単語があり、クリストファーという名前の俳優がいるすべてのレコードが表示されます。ここexpertにあるサンプル アプリケーション テンプレートのテンプレートに示されているように、複数のフィルターを使用できます。

于 2016-04-29T18:06:43.887 に答える
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/

これで、すべてのインデックス フィールドを検索できるようになりました。

于 2015-11-26T13:16:43.163 に答える