仅返回包含数组中所有ID的关联记录

时间:2018-12-08 05:41:08

标签: ruby-on-rails postgresql activerecord

说我有以下表格和关系:

class Book has_many :book_genres end

class Genre has_many :book_genres end

class BookGenre belongs_to :book belongs_to :genre end

如果我只想查找具有两个特定流派ID(13005和9190)的图书,

我以为我可以做类似的事情:

Book.where(book_genres: {genre_id: [13005, 9190]})

但是它返回的图书的类型为ID 13005或9190。

我还认为也许可以通过执行以下操作将其过滤掉:

Book.where(book_genres: {genre_id: [13005]}).where(book_genres: {genre_id: [9190]})

但这也不起作用。

我如何只查找包含两个ID的流派的图书?

注意:

在这篇文章(https://stackoverflow.com/a/3416838/1778314)中,我尝试这样做:

Book.joins(:book_genres).where(book_genres: { genre_id: [13005,9190]}).group("books.id").having("count(book_genres.id) = #{[13005, 9190].count}")

但这都不起作用(返回两个集合)。

此外,还有一篇类似的文章使用食谱和配料,但没有有效的解决方案:Ruby On Rails 5, activerecord query where model association ids includes ALL ids in array

3 个答案:

答案 0 :(得分:1)

具有两个特定类型ID(13005和9190)的图书,

book_ids_either_have_two_ids = Book. includes(:book_genres).where("book_genres.id IN ?= [3005 9190]")distinct.pluck(:id)

Book.where.not("id IN ?", book_ids_either_have_two_ids)

答案 1 :(得分:0)

我知道下面的方法不是很熟练,但是可以解决您的问题,

Book.includes(:book_genres).select { |book| book.book_genres.map(&:genre_id).uniq.sort == [9190, 13005] }

以上将返回Array类型而不是ActiveRecord::Relation的输出,但是它将根据您的要求工作。

答案 2 :(得分:0)

这对我有用:

Book.joins(:book_genres).where(book_genres: { genre_id: [13005, 205580]}).group("books.id").having('count(books.id) >= ?', [13005, 205580].size)