Rails 7 多对多关系,搜索具有多个相关项目的项目

问题描述 投票:0回答:2

假设我在 Rails 7 中有三个模型、一些项目、标识符和一个连接模型

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%")

假设我有一个项目并且它有两个标识符

foo
bar
我有以下搜索

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

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

ruby-on-rails ruby activerecord rails-activerecord ruby-on-rails-7
2个回答
0
投票

经过更多搜索后找到答案这里

解决方案是将以下内容添加到我的项目模型中

    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)

0
投票

如果您想按标识符组合进行过滤,则需要使用

UNION
SELECT FROM SELECT

Union
可以连接两个不同的选择,是一个更好的选择,但是 Rails 没有一个漂亮的解决方案,需要使用 Arel 表。这是一个示例:在 ActiveRecord 中获取并集所有结果

Select from Select
是更糟糕的解决方案,因为除了创建
VIEW
然后从中进行选择之外,Rails 没有任何正常的方法可以做到这一点。所以使用这种方法你唯一能做的就是使用纯 SQL 来发出请求。

作为替代方案,您可以删除

LIKE
语句并仅使用普通的
WHERE identifier = 'foo' AND identifier = 'bar'
,但为此您需要传递确切的标识符。

总结

在我看来 -

UNION
将是正确的解决方案,所以我建议您了解一下 Arel 表,因为它是一个非常强大的工具。这是一些链接:

https://www.rubydoc.info/docs/rails/Arel/Table

https://devhints.io/arel

© www.soinside.com 2019 - 2024. All rights reserved.