是否可以检查 has_many 中是否存在多个关联?在这种情况下,我想检查是否有一本书具有三个标签“a”、“b”和“c”。
(书和标签通过多对多关联。)
if Book.all.tags.find("a", "b", "c").any?
# Yay!
# There is at least one book with all three tags (a, b & c)
end
是否可以检查 has_many 中是否存在多个关联?在这种情况下,我想检查是否有一本书具有三个标签“a”、“b”和“c”。
(书和标签通过多对多关联。)
if Book.all.tags.find("a", "b", "c").any?
# Yay!
# There is at least one book with all three tags (a, b & c)
end
我认为这可以解决问题(适用于has_many
):
Book.includes(:tags).where(tags: { name: ['a', 'b', 'c'] }).any?
分解它:
这includes
告诉 Rails 使用预先加载来加载标签,而不是一次加载一个。这也导致它tags
在查询中注意并生成更智能的查询。
where
条件非常简单,传递数组只是将比较=
转换为IN ('a', 'b', 'c')
条件。
Railsany?
对 .
我使用这个查询结构:
Book
.select('distinct books.*')
.joins(:tags)
.where('tags.slug' => ['a', 'b', 'c'])
.group("pages.id")
.having("count(*) = #{['a', 'b', 'c'].size}")
我从来没有找到一种优雅的方式来解决这个问题,所以希望其他人能提供更好的答案。
野蛮的方法是下拉到sql。我是在内存不足的情况下写的,所以可能存在语法问题。
Book 模型中的类似内容。表的短名称不会与父查询冲突。
def self.with_tag(tag)
where("EXISTS (SELECT 1 from books_tags bt, tags t where bt.tag_id = t.id
and bt.book_id = books.id and t.name = ?)", tag)
end
然后你会调用Book.with_tag('a').with_tag('b').with_tag('c')
或定义另一个方法。不确定是否需要范围变量。
def self.with_all_tags(tags)
scope = self.scoped
tags.each do |t|
scope = scope.with_tag(t)
end
end