按数组中的所有 id 过滤
Filter by all ids in an array
我有两个模型,都具有 has_and_belongs_to_many
关系。
class Movie < ApplicationRecord
has_and_belongs_to_many :genres
end
class Genre < ApplicationRecord
has_and_belongs_to_many :movies
end
例如,在电影索引页面上,我希望能够按流派进行过滤。对于过滤器表单,我有一个多 select 流派框,当提交时发送一个 id 数组。
如何使用 Active Record 找到匹配数组中所有这些 ID 的电影,而不是仅匹配任何 ID 的电影?例如,如果用户 select 是恐怖片和喜剧片,它应该过滤到同时是恐怖片和喜剧片的电影,而不仅仅是任何恐怖片或任何喜剧片。
ids = params[:genres]
Movie.includes(:genres).where(genres: {id: ids})
以上示例查找任何一部恐怖片或喜剧片。
通过使用 joins
与 group
和 having
解决了这个问题。
ids = params[:genres]
Movie.joins(:genres)
.where(genres: {id: ids})
.group(:id)
.having("count(*) = #{ids.count}")
这基本上会过滤掉重复的匹配项,return 只会过滤掉与原始数组计数结果数量相同的电影。这意味着如果数组计数为 3,则只有从原始 joins
查询中获得 3 个结果的电影才会匹配。
我有两个模型,都具有 has_and_belongs_to_many
关系。
class Movie < ApplicationRecord
has_and_belongs_to_many :genres
end
class Genre < ApplicationRecord
has_and_belongs_to_many :movies
end
例如,在电影索引页面上,我希望能够按流派进行过滤。对于过滤器表单,我有一个多 select 流派框,当提交时发送一个 id 数组。
如何使用 Active Record 找到匹配数组中所有这些 ID 的电影,而不是仅匹配任何 ID 的电影?例如,如果用户 select 是恐怖片和喜剧片,它应该过滤到同时是恐怖片和喜剧片的电影,而不仅仅是任何恐怖片或任何喜剧片。
ids = params[:genres]
Movie.includes(:genres).where(genres: {id: ids})
以上示例查找任何一部恐怖片或喜剧片。
通过使用 joins
与 group
和 having
解决了这个问题。
ids = params[:genres]
Movie.joins(:genres)
.where(genres: {id: ids})
.group(:id)
.having("count(*) = #{ids.count}")
这基本上会过滤掉重复的匹配项,return 只会过滤掉与原始数组计数结果数量相同的电影。这意味着如果数组计数为 3,则只有从原始 joins
查询中获得 3 个结果的电影才会匹配。