繁体   English   中英

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

[英]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.rbActiveSupport::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM