【问题标题】:ILIKE for multiple columns with Arel and Ransack使用 Arel 和 Ransack 对多列进行 ILIKE
【发布时间】:2023-05-24 00:28:01
【问题描述】:

我正在使用 Ransack 搜索和 Postgresql 数据库。

我有一个输入需要使用“ILIKE”(文本列)在两个不同的列中进行搜索。

首先我创建了这个 ransacker:

ransacker :number do
  Arel.sql("invoice_number::text")
end

效果很好:

Purchase.ransack({number_cont: "123"}).result.to_sql
# => "SELECT \"purchases\".* FROM \"purchases\" WHERE (invoice_number::text ILIKE '%123%')"

但是,我现在想使用相同的输入(所以,相同的 ransacker)在另一列中搜索。

我试过这样做:

ransacker :number do |parent|
  Arel::Nodes::InfixOperation.new('OR', parent.table["invoice_number::text"], parent.table["shipping_number::text"])
end

返回:

Purchase.ransack({number_cont: "123"}).result.to_sql
# => "SELECT \"purchases\".* FROM \"purchases\" WHERE (\"purchases\".\"invoice_number::text\" OR \"purchases\".\"shipping_number::text\" ILIKE '%123%')"

所以你可以看到与我需要的没有什么不同,即:

"column1::text ILIKE '%123%' OR column2::text ILIKE '%123%'"

你知道我该怎么做吗?

【问题讨论】:

    标签: ruby-on-rails postgresql arel ransack


    【解决方案1】:

    这不是您想要的,但它看起来像 ransack gem,如果您在查询参数名称中组合多个字段,它可以工作:

    class Purchase < ApplicationRecord
      ransacker :number do
        Arel.sql("invoice_number::text")
      end
    
      ransacker :shipping do
        Arel.sql("shipping_number::text")
      end
    end
    
    puts Purchase.ransack(shipping_or_number_cont: '123').result.to_sql
    # => SELECT "purchases".* FROM "purchases"
    #  WHERE (shipping_number::text LIKE '%123%' OR invoice_number::text LIKE '%123%')
    

    因此,如果您能够调整参数名称,这可能比尝试在 ransacker 块内进行调整更容易

    【讨论】:

      【解决方案2】:

      我在 mysql 中进行以下操作,这对我有用

      ransacker :invoice_number_or_shipping_number, formatter: proc { |v|
        Purchase.where("invoice_number LIKE ? OR shipping_number LIKE ?", "%#{v}%", "%#{v}%").map(&:id).empty? ?
        "SELECT NULL FROM DUAL WHERE 0 " : Purchase.where("invoice_number LIKE ? OR shipping_number LIKE ?", "%#{v}%", "%#{v}%").map(&:id)
        }, splat_param: true do |parent|
        parent.table[:id]
      end
      

      【讨论】: