ruby Rails7多对多关系,搜索具有多个相关项的项

eni9jsuy  于 12个月前  发布在  Ruby
关注(0)|答案(2)|浏览(77)

假设我有三个模型,一些项目,标识符和Rails7中的连接模型

class Item < ApplicationRecord
  has_many :item_identifiers
  has_many :identifiers, through: :item_identifiers
end

class ItemIdentifier < ApplicationRecord
  belongs_to :item
  belongs_to :identifier
end

class Identifier < ApplicationRecord
  has_many :item_identifiers
  has_many :items, through: :item_identifiers
end

这样,我就可以从项目中访问标识符,

item.identifiers

我可以在数据库中搜索一个带有标识符的项目

Item.joins(:identifiers).where("`identifiers`.`desc` LIKE %foo%")

假设我有一个项目,它有两个标识符foobar,我有以下搜索

search1 = ["oo"]
search2 = ["foo", "ar"]
search3 = ["fo", "baz"]

如何查找具有多个标识符的项目。根据上面的搜索数组,search1和search2都应该找到该项目,但search3不应该。

wydwbb8l

wydwbb8l1#

经过多次搜索,找到了答案。
解决方案是将以下内容添加到我的项目模型中

def self.with_identifiers(identifiers)
        sql = identifiers.
          map { |identifier| Item.joins(identifiers).where("identifiers.desc LIKE ?", "%#{identifier}%") }.
          map { |relation| "(#{relation.to_sql})" }.
          join(" INTERSECT ")
      
        find_by_sql(sql)
      end

并使用以下内容进行搜索

Item.with_identifiers(search1)
hfwmuf9z

hfwmuf9z2#

如果你想通过标识符的组合进行过滤,那么你需要使用UNIONSELECT FROM SELECT
Union可以连接两个不同的选择,是一个更好的选择,但Rails没有一个漂亮的解决方案,需要使用Arel表。下面是一个例子:Obtain Union all result in ActiveRecord
Select from Select是更糟糕的解决方案,因为Rails除了创建一个VIEW然后从中选择之外,没有任何正常的方法来做到这一点。所以使用这种方法唯一能做的就是使用纯SQL发出请求。
作为替代方案,您可以删除LIKE语句并使用普通的WHERE identifier = 'foo' AND identifier = 'bar',但为此您需要传递确切的标识符。

WRAPUP

在我看来-UNION将是正确的解决方案,所以我会建议你学习一点关于Arel表,因为它是一个非常强大的工具。这里有一些链接:
https://www.rubydoc.info/docs/rails/Arel/Table
https://devhints.io/arel

相关问题