查询Activerecord HABTM关系以包含数组的所有元素
我有一个Forum
和ForumTag
关系。 我还有一个名为@tags
的变量数组。 此数组包含一些ForumTags的名称。 我希望能够查询并查找具有该数组所有值的所有论坛。 我目前有:
@forums = Forum.joines(:forum_tags).where(:forum_tags => {:name => @tags})。includes(:forum_tags).all
但是,这将返回arrays中至少具有一个值的所有论坛。
以下将要求论坛在@tags
数组中包含所有论坛标记。 我假设一个forum
不会多次拥有相同的forum_tag
。
@forums = Forum.joins(:forum_tags).where(:forum_tags => {:name => @tags}).group("forums.id").having(['COUNT(*) = ?', @tags.length]).includes(:forum_tags).all
这将生成如下SQL查询:
@tags = ['foo', 'bar'] SELECT forums.id, forum_tags.id FROM forums LEFT OUTER JOIN forum_tags_forums on forum_tags_forums.forum_id = forums.id LEFT OUTER JOIN forum_tags ON forum_tags.id = forum_tags_forums.forum_tag_id WHERE forum_tags.name IN ('foo', 'bar') GROUP BY forums.id HAVING COUNT(*) = 2;
这将通过与给定标记匹配的论坛对连接表中的所有行进行分组。 如果COUNT
函数具有您要查找的标记总数的值(并且没有重复的forum
/ forum_tag
对),则论坛必须包含所有标记。
要获得剩余的标签(评论中提出的问题):
forum_tags = ForumTag.where(:name => @tags) @forums_with_leftovers = Forum.select("forums.*, GROUP_CONCAT(forum_tags.name) AS leftover_tags").joins(:forum_tags).where(['forums.id IN (?) AND NOT forum_tags.id IN (?)', @forums, forum_tags]).group("forums.id").all
@forums_with_leftovers
每个Forum
对象都有一个额外的属性@forums_with_leftovers
,其中包含每个论坛对象中不包含在原始@tags
变量中的逗号分隔的标记列表。