1

我有一个 Book 模型、一个 User 模型和一个 Read 模型。一本书可以有很多阅读,一个用户可以有很多阅读。基本上,在阅读中是某个用户已阅读的所有书籍。

现在我想显示某个用户的所有未读书籍的列表。假设用户已登录并且有一个 current_user 对象,我将如何获得这样的列表?

我目前有这个:

@unread_books = Book.find(:all, include: :reads, conditions: ["books.id NOT IN (?)", current_user.read_ids])

但这会将书籍 ID 映射到阅读 ID。它应该是这样的:

conditions: ["books.id NOT IN (?)", current_user.read_book_ids]

但这给出了一个错误:

undefined method `read_book_ids' for #<User:0x007fb21782b3f8>

那么,如何将书籍 ID 映射到 Read 中的外键书籍 ID?

4

1 回答 1

1

使用LEFT OUTER JOIN获取这些书籍;当前用户 id 有或没有读过的书。然后只选择那些没有附加用户的书籍,它们包含在外部连接中(但不包含在内部连接中)。这些正是当前用户尚未阅读的书籍:

SELECT books.id, books.title FROM books
LEFT OUTER JOIN readings 
  ON readings.book_id = books.id 
  AND readings.user_id = 1
WHERE readings.user_id IS NULL

SQLFiddle 上的测试。

在 Rails 中,这可能是这样的(未经测试):

Books.joins("LEFT OUTER JOIN reads\
  ON reads.book_id = books.id\
  AND reads.user_id = :user_id", user_id: current_user.id)
.where("reads.user_id IS NULL")

您的方法的问题在于,您可能会传递大量要忽略的 id。这必须搜索每个条目的 id,这是非常低效的。

于 2013-05-26T09:30:19.423 回答