3

これは図書館システムで、ここで本を借りることができます。そして、各本はカテゴリーに属しています。一番借りた本の種類に応じて、いくつかの提案をしたいと思います。

4つのモデルがあります:

class Person < AR
  has_many :borrows
end


class Borrow < AR
  belongs_to :person
  belongs_to :book
end

class Category < AR
  has_many :books
end

class Book < AR
  has_many :borrows
  belongs_to :category
end

そして私は本を見つけるためにSQLを書きました


SELECT * FROM books WHERE category_id = 
  (SELECT category_id FROM books WHERE id IN
    (SELECT book_id FROM borrows WHERE person_id =10000)
  GROUP BY category_id ORDER BY count(*) DESC LIMIT 1)
AND id NOT IN
  (SELECT book_id FROM borrows WHERE person_id =10000)

これは機能しているようですが、どうすればRailsの方法でファインダーを作成できるのでしょうか...

4

3 に答える 3

2

次のことができます。 person.rb に次のように記述します。

has_many :books, :through => :borrows
has_many :categories_of_books, :through => :books,  :source => :category

&

def suggested_books
 Book.where("category_id IN (?) AND id NOT IN (?)",  self.categories_of_books, self.books)
end

結果は複数のクエリになりますが、クリーンですが、次のことを行う必要があります。

   @user.suggested_books
于 2012-11-21T11:24:14.753 に答える
1

アクティブレコードを使用すると、3つのサブクエリのうち2つを削除して、結合を優先できます。

Book.where(
  category_id: Category.limit(1)
    .joins(:books => :borrows)
    .where("borrows.person_id = ?", 10000)
    .group("categories.id")
    .order("COUNT(*) DESC")
    .pluck("categories.id")
  ).joins(:borrows).where("borrows.person_id != ?", 10000)

それでも2つの別々のクエリ(1つはの内部クエリ用)を生成するため、最善の解決策ではありませんCategory。ニーズによっては、これはそれほど悪くない場合があります。たとえば、内部クエリの結果(問題のユーザーの最も借用されたカテゴリ)を他の目的に使用することにした場合です。

于 2012-11-21T09:24:00.933 に答える
0

そのようなものかもしれません:

@person = Person.find(10000)
@categories = @person.books.map{|b| b.category}.uniq!
@suggestions = @categories.map{|c| c.books} - @person.books

「@person.books」を機能させるには、Person モデルを追加する必要があります。

has_many :books, :through => :borrows
于 2012-11-21T08:09:52.777 に答える