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

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

def self.search query
  __elasticsearch__.search(
    query: {
      multi_match: {
        query: query,
        fields: %w[title actor.name]
      }
    }
  )
end
于 2017-11-11T10:02:45.903 回答
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 回答
0

尝试这个

indexes :actors do
 indexes :name, type: "string"
end
于 2015-11-05T13:36:23.507 回答