【问题标题】:Query and Eager-Load Associations查询和急切关联
【发布时间】:2026-02-17 13:10:02
【问题描述】:

我有 2 个模型,需要查询以下字段。

  • Customer

    • :first_name
    • :last_name
    • :address
    • :email
  • Relatives

    • :first_name
    • :last_name
    • :address
    • :title

一个Customer 有很多Relatives

我正在尝试编写一个 search() 方法,该方法将返回 Customer 记录的集合,其中 任一 Customer 的字段或其中 1+ 的相关 Relatives 匹配查询。

目标是能够迭代Customer 记录的集合。如果customer.relatives.present?,我会知道循环通过Customer 提供的相关Relative 模型 - 该集合中的模型与查询匹配。

我目前有这样的事情:

class Customer < ActiveRecord::Base

  has_many :relatives

  def self.search(params={})
    cols  = %i(address caseworker last_name)
    conds = []

    cols.reject! { |col| params[col].blank? }

    conds << cols.collect { |col| "clients.#{col} like ?" }.join(" or ")
    cols.each { |col| conds << "%#{params[col]}%" }

    query = self.send(:where, conds)

    # @todo query relatives here!    
  end

end

我卡住的地方:

  • 我不知道要加入/合并/联合/(我不知道我要查找的术语)与搜索不匹配的 Customer 模型,但 这样做 有一个匹配搜索的Relative
    • 我相信我需要在 Relative 模型上几乎相同的 search() - 我相信我可以写 - 但我再次不确定如何填写上面的 @todo 以仅急切加载匹配的 Relative查询。

我正在寻找正确方向的任何颠簸。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 arel


    【解决方案1】:

    根据您的数据库,您可能需要查看 pg_search 之类的内容以进行全文搜索。

    在建立搜索索引后,与客户查询匹配的预加载亲戚是微不足道的。

    class Customer < ActiveRecord::Base
      include PgSearch
      has_many :relatives
    
      pg_search_scope :search,
        :against => [:address, :caseworker, :last_name]
        :associated_against => {
        :relatives => [:address, :caseworker, :last_name]
      }
    end
    
    Customer.search("foobar").preload(:relatives)
    

    【讨论】:

    • 这真的很有趣。你知道 MySQL 的等价物吗?
    • 另外,preload(:relativates) 将加载 所有 亲属,当我只对那些专门导致 Customer 包含在原始集合中的人感兴趣时。
    • 我对 MySQL 中的全文搜索没有任何经验,但 Thinking Sphinx (pat.github.io/thinking-sphinx) 看起来很有前途
    • 抱歉,我错过了只急切加载与查询匹配的亲属的要求。我会考虑的..
    【解决方案2】:

    这个gem是mysql数据库搜索和全文搜索的简单实现https://github.com/makandra/dusen

    您可能需要进行一些编码才能使 gem 正常工作,例如定义 search_text 等。但是这个 gem 会处理剩下的事情。

    【讨论】: