2014-12-20 36 views
5

我有一個名爲Movie模型,看起來像這樣:Elasticsearch軌/ Elasticsearch新型檢索模型關聯

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

我可以對索引做些什麼改變來搜索與搜索到的演員相關的電影?

+1

我有同樣的困境,你有沒有這方面的任何答覆? – Finks

回答

0

我以前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 

我在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我得到它有所有的記錄在他們的頭銜上有一個未來的未來,並且有一個名叫克里斯托弗的演員您可以使用示例應用程序模板found hereexpert模板所示的多個過濾器。

0

試試這個

indexes :actors do 
indexes :name, type: "string" 
end 
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/

現在你可以搜索所有索引字段。

0

你需要指定在該領域的search方法,如:

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