假设我在 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 不应该找到。
经过更多搜索后找到答案这里
解决方案是将以下内容添加到我的项目模型中
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)
如果您想按标识符组合进行过滤,则需要使用
UNION
或 SELECT FROM SELECT
。
Union
可以连接两个不同的选择,是一个更好的选择,但是 Rails 没有一个漂亮的解决方案,需要使用 Arel 表。这是一个示例:在 ActiveRecord 中获取并集所有结果
Select from Select
是更糟糕的解决方案,因为除了创建 VIEW
然后从中进行选择之外,Rails 没有任何正常的方法可以做到这一点。所以使用这种方法你唯一能做的就是使用纯 SQL 来发出请求。
作为替代方案,您可以删除
LIKE
语句并仅使用普通的 WHERE identifier = 'foo' AND identifier = 'bar'
,但为此您需要传递确切的标识符。
总结
在我看来 -
UNION
将是正确的解决方案,所以我建议您了解一下 Arel 表,因为它是一个非常强大的工具。这是一些链接: