0

ElasticSearchとTireが結果を返さないという問題があります。Ruby1.9.3とRails3.2.11を使用しています。

私のコントローラーでは、次のように呼び出しています。

@location_id = 1
@listings = Listing.search(params.merge!(location_id: @location_id))

私のリストモデルには

mapping do
    indexes :id, type: 'integer'
    ...
    indexes :author do
      indexes :location_id,     :type => 'integer', :index => :not_analyzed
      ...
end

def self.search(params={})
      tire.search(load: true, page: params[:page], per_page: 20) do |search|

      search.query  { string params[:query], :default_operator => "AND" } if params[:query].present?
      search.filter :range, posted_at: {lte: DateTime.now}

      search.filter :term, "author.location_id"       => params[:location_id]
end

データベースにlocation_idが1の300件の結果があるので、なぜnilセットが返されるのか理解できないようです。author.location_id検索フィルター行をコメントアウトすると、他のすべての結果が期待どおりに返されますか?

4

1 に答える 1

1

あなたのような状況で対処する必要があるいくつかのことがあります。完全に機能するコードから始めましょう:

require 'active_record'
require 'tire'
require 'logger'

# Tire.configure { logger STDERR }
# ActiveRecord::Base.logger = Logger.new(STDERR)

Tire.index('articles').delete

ActiveRecord::Base.establish_connection( adapter: 'sqlite3', database: ":memory:" )
ActiveRecord::Schema.define(version: 1) do
  create_table :articles do |t|
    t.string :title
    t.integer :author_id
    t.date    :posted_at
    t.timestamps
  end
  create_table :authors do |t|
    t.string  :name
    t.integer :number, :location_id
    t.timestamps
  end
  add_index(:articles, :author_id)
  add_index(:authors, :location_id)
end

class Article < ActiveRecord::Base
  belongs_to :author, touch: true
  self.include_root_in_json = false

  include Tire::Model::Search
  include Tire::Model::Callbacks

  mapping do
    indexes :title

    indexes :author do
      indexes :location_id, type: 'integer'
    end
  end

  def self.search(params={})
    tire.search load: {include: 'author'} do |search|
      search.query do |query|
        query.filtered do |f|
          f.query { params[:query].present? ? match([:title], params[:query], operator: 'and') : match_all }
          f.filter :range, 'posted_at' => { lte: DateTime.now }
          f.filter :term,  'author.location_id' => params[:location_id]
        end
      end
    end
  end

  def to_indexed_json
    to_json( only: ['title', 'posted_at'], include: { author: { only: [:location_id] } } )
  end
end

class Author < ActiveRecord::Base
  has_many :articles

  after_touch do
    articles.each { |a| a.tire.update_index }
  end
end

# -----

Author.create id: 1, name: 'John', location_id: 1
Author.create id: 2, name: 'Mary', location_id: 1
Author.create id: 3, name: 'Abby', location_id: 2

Article.create title: 'Test A', author: Author.find(1), posted_at: 2.days.ago
Article.create title: 'Test B', author: Author.find(2), posted_at: 1.day.ago
Article.create title: 'Test C', author: Author.find(3), posted_at: 1.day.ago
Article.create title: 'Test D', author: Author.find(3), posted_at: 1.day.from_now

Article.index.refresh

# -----

articles = Article.search query: 'test', location_id: 1
puts "", "Documents with location:1", '-'*80
articles.results.each { |a| puts "* TITLE: #{a.title}, LOCATION: #{a.author.location_id}, DATE: #{a.posted_at}" }

articles = Article.search query: 'test', location_id: 2
puts "", "Documents with location:2", '-'*80
articles.results.each { |a| puts "* TITLE: #{a.title}, LOCATION: #{a.author.location_id}, DATE: #{a.posted_at}" }
puts "(NOTE: 'D' is missing, because is not yet posted)"

articles = Article.search query: 'test b', location_id: 1
puts "", "Documents with query:B and location:1", '-'*80
articles.results.each { |a| puts "* TITLE: #{a.title}, LOCATION: #{a.author.location_id}, DATE: #{a.posted_at}" }

まず、通常、このように分離され、抽出されたケースを作成することをお勧めします。

サンプルコードでは、関係があると想定していますListing belongs_to :author。マッピングとシリアル化を適切に定義する必要があります。これもまた、あなたが行ったと思います。

クエリ自体について:

  • ファセットナビゲーションを使用している場合を除きfiltered、サンプルコードのように、トップレベルのフィルターではなくクエリを使用してください。

  • stringLuceneクエリ文字列クエリのすべての機能(および脆弱性!)をユーザーに公開したい場合を除いて、クエリを使用しないでください。

  • matchクエリを「汎用」クエリとして使用します。タイヤmulti_matchに砂糖をまぶして、クエリなどを簡単に作成できるようにします。

  • あなたの例のフィルター構文は正しいです。このメソッドがTirefilterで複数回呼び出されると、作成およびフィルタリングされます。and

タイヤロギング構成(および場合によってはActiveRecordロギングも)のコメントを解除して、コードが何をしているかを確認します。

于 2013-02-06T18:09:44.950 に答える