使用ElasticSearch + Tire搜索多个术语

时间:2012-12-21 21:42:36

标签: ruby-on-rails ruby mongoid elasticsearch tire

将Tire与Mongoid一起使用,我无法弄清楚如何构建查询以使用ElasticSearch查找事件。特别是,我正在尝试查找用户正在观看的事件以及用户遵循的表演者的事件:

# app/models/event.rb
class Event
  include Mongoid::Document
  include Tire::Model::Search
  include Tire::Model::Callbacks

  field :name, type: String

  has_and_belongs_to_many :performers
  has_many :watchers, class_name: 'User'

  mapping do
    indexes :name
    indexes :watcher_ids, type: 'string', index: :not_analyzed
    indexes :performer_ids, type: 'string', index: :not_analyzed
  end
end

以下查询仅适用于观察者或表演者。

Tire.search 'events' do
  query do
    string params[:query]
    # Only one of these will work at a time:
    terms :performer_ids, current_user.followed_performers.collect(&:id).map(&:to_s)
    terms :watcher_ids, [current_user.id.to_s]
  end
end
  • 小编辑,因为我输错了我的例子。

这是一个似乎“有效”的解决方案......但感觉不对

Tire.search('events') do
  query do
    boolean do
      should { string params[:query] }
      should { string "performer_ids:#{current_user.followed_performers.collect(&:id).map(&:to_s).join(',')}" }
      should { string "watcher_ids:#{current_user.id.to_s}" }
    end
  end
end

2 个答案:

答案 0 :(得分:4)

你走的是正确的道路,但正如Russ Smith建议的那样,你需要使用filter DSL。

现在,如果您只是反复拨打filter,则会执行联合:AND。如果您想要返回 事件用户正在观看用户关注的表演者,则必须使用or过滤器。

此外,为了获得最佳性能,请使用filtered查询,而不是顶级过滤器 - 在前一种情况下,过滤器首先运行,切割语料库并仅对此子集执行查询。

代码应如下所示:

Tire.search 'events' do
  query do
    filtered do
      query do
        string params[:query]
      end
      filter :or, terms: { organization_ids: current_user.followed_performers.collect(&:id).map(&:to_s) },
                  terms: { watcher_ids:      [current_user.id.to_s] }
    end
  end
end

有关更多示例,请参阅集成测试:

答案 1 :(得分:2)

我认为你要找的是过滤器。这不是经过完全测试的代码,但它可能会引导您朝着正确的方向发展。

class Event
  include Mongoid::Document
  include Tire::Model::Search
  include Tire::Model::Callbacks

  field :name, type: String

  has_and_belongs_to_many :performers
  has_many :watchers, class_name: 'User'

  mapping do
    indexes :name
    indexes :watcher_ids, type: 'integer', index: :not_analyzed
    indexes :performer_ids, type: 'integer', index: :not_analyzed
  end
end

Tire.search('events') do
  query do
    string 'my event'
  end

  filter :in, :organization_ids, [1,2,3]
  filter :in, :watcher_ids, [1]
end