【问题标题】:Searching Multiple Terms with ElasticSearch + Tire使用 ElasticSearch + Tire 搜索多个术语
【发布时间】:2012-12-09 11:21:11
【问题描述】:

将 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

【问题讨论】:

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


    【解决方案1】:

    您走在正确的道路上,但按照 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
    

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

    【讨论】:

    • 谢谢大家,我已经尝试了这两个示例,但我的测试都失败了。 @karmi 在尝试您的示例时,它返回 watcher_ids 但不返回其他术语... "filter":{"and":[{"or":{"terms":{"watcher_ids":[....
    • 好的,我花了一些时间来解决这个问题,但我仍然没有得到我想要的结果。我没有使用过滤器,因为布尔值无法满足我的需要。这就是我所拥有的......gist.github.com/4383340你看到我错过了什么吗?
    • 1.我不明白“它返回 watcher_ids 但不返回其他术语”是什么意思。 2. 我不明白“布尔值不能按我的需要工作”是什么意思。 3. Russ 和 /me 发布的代码绝对应该适用于概述的情况——也许尝试将行为隔离到普通的 Ruby 中? 4. 我无法阅读链接要点中代码的意图:为什么使用multi_search 进行单一搜索,为什么将所有内容都包装在relevant_events 方法中?
    • 抱歉,通过 cmets 进行通信使事情变得更加困难。 multi_search 的原因是因为我使用的大约 70% 的代码被删除了,所以只显示了与我的问题相关的代码。我的问题是我有一组要搜索的对象 ID。使用带有或的过滤器,我没有得到任何结果。使用布尔值,我确实得到了结果。布尔值的问题是每个“应该”都是必需的。因此,如果 performer_ids 为空,则查询失败。我敢肯定这是一个简单的修复,但我已经坚持了一段时间。有没有更好的地方发布关于轮胎的问题?
    • 是的,Github 问题运行得相当好...您应该能够使用or 过滤器实现与布尔型string 查询相同的功能...
    【解决方案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
    

    【讨论】:

    • nope :( 它失败了。如果我把所有东西都扔进一个布尔值,里面有一堆 should { string ''} 那么它就可以工作了..
    • 从头开始。它并没有真正起作用,因为它需要所有参数才能返回结果。回到尝试使用过滤器...
    猜你喜欢
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多