Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/53.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails:在订购联接表后删除重复项_Ruby On Rails - Fatal编程技术网

Ruby on rails Rails:在订购联接表后删除重复项

Ruby on rails Rails:在订购联接表后删除重复项,ruby-on-rails,Ruby On Rails,我有一本书有很多评论,我在书中添加了一个类方法,在我的主页上显示“最近评论”的书。我试过这个: def self.recently_reviewed Book.joins(:reviews).order('reviews.created_at DESC').limit(5) end 这会产生许多重复记录,因此我尝试使用distinct like so: Book.joins(:reviews).order('reviews.created_at DESC').distinct.limit(

我有一本书有很多评论,我在书中添加了一个类方法,在我的主页上显示“最近评论”的书。我试过这个:

def self.recently_reviewed
  Book.joins(:reviews).order('reviews.created_at DESC').limit(5)
end
这会产生许多重复记录,因此我尝试使用distinct like so:

Book.joins(:reviews).order('reviews.created_at DESC').distinct.limit(5)
我在点餐前后也试过了

对于如何解决这个问题,我感到有点困惑,我是否应该选择。选择以获得更大的灵活性?

中的

Book.joins:reviews.order'reviews.created_at DESC'。不同

您正在尝试从书籍和评论的联接表中选择不同的预订,然后根据reviews.created_对该不同预订列表进行排序。SQL将如下所示:

SELECT DISTINCT "books"."id" FROM "books" INNE JOIN "reviews" ON "reviews"."book_id" = "books"."id" ORDER BY reviews.created_at
这是不允许的一个很好的理由。因为结果是不确定的。假设一本书有100篇评论。在join表中,这本书有100行,包含所有不同的评论。当您选择一个不同的列表时,您将得到这本书的一行。这可以是联接表中100个变量中的任意一个。然后,您根据此评论的创建时间来订购。由于审查可能是100项中的任何一项,因此每次审查的顺序都可能不同

这将是非常好的:

Book.joins:reviews.order'books.id DESC'。不同

因为它为那本书选择100行中的哪一行并不重要,books.id是相同的

回到你的问题上来。看来你想得到5本最近有评论的书。我看不出一个简单的方法,但以下是我的解决方案:

res = Review.group("book_id").maximum("created_at") # {book_id => create_at}, each book with its most recent review time
arr = res.to_a.sort { |a,b| b[1]<=>a[1] } #array sorted by created_at in desc order
arr.map{ |n| n[0] }.take(5)  #top 5 books' ids with most recent reviews

Book.joins:reviews.order'reviews.created_at DESC'。不同

您正在尝试从书籍和评论的联接表中选择不同的预订,然后根据reviews.created_对该不同预订列表进行排序。SQL将如下所示:

SELECT DISTINCT "books"."id" FROM "books" INNE JOIN "reviews" ON "reviews"."book_id" = "books"."id" ORDER BY reviews.created_at
这是不允许的一个很好的理由。因为结果是不确定的。假设一本书有100篇评论。在join表中,这本书有100行,包含所有不同的评论。当您选择一个不同的列表时,您将得到这本书的一行。这可以是联接表中100个变量中的任意一个。然后,您根据此评论的创建时间来订购。由于审查可能是100项中的任何一项,因此每次审查的顺序都可能不同

这将是非常好的:

Book.joins:reviews.order'books.id DESC'。不同

因为它为那本书选择100行中的哪一行并不重要,books.id是相同的

回到你的问题上来。看来你想得到5本最近有评论的书。我看不出一个简单的方法,但以下是我的解决方案:

res = Review.group("book_id").maximum("created_at") # {book_id => create_at}, each book with its most recent review time
arr = res.to_a.sort { |a,b| b[1]<=>a[1] } #array sorted by created_at in desc order
arr.map{ |n| n[0] }.take(5)  #top 5 books' ids with most recent reviews

这实际上是一个比ActiveRecord以最简单的形式处理更复杂的DB查询,因为它需要一个子查询。下面是我如何完全通过一个查询来实现这一点:

SELECT   book.*
FROM     book
         INNER JOIN books on reviews.book_id = books.id
WHERE    reviews.created_on = ( SELECT  MAX(reviews.created_at)
                              FROM    reviews
                              WHERE   reviews.book_id = books.id)
GROUP BY books.id
要将其转换为ActiveRecord,我将执行以下操作:

class Book
  scope :recently_reviewed, joins(:reviews)
    .where('reviews.created_on = (SELECT MAX(books.created_at) FROM reviews WHERE reviews.book_id = books.id)')
    .group('books.id')
end
Book.recently_reviewed
然后,通过执行以下操作,您可以获得所有上次审阅的书籍的列表:

class Book
  scope :recently_reviewed, joins(:reviews)
    .where('reviews.created_on = (SELECT MAX(books.created_at) FROM reviews WHERE reviews.book_id = books.id)')
    .group('books.id')
end
Book.recently_reviewed
然后,您可以通过

Book.recently_reviewed.limit(n)

这实际上是一个比ActiveRecord以最简单的形式处理更复杂的DB查询,因为它需要一个子查询。下面是我如何完全通过一个查询来实现这一点:

SELECT   book.*
FROM     book
         INNER JOIN books on reviews.book_id = books.id
WHERE    reviews.created_on = ( SELECT  MAX(reviews.created_at)
                              FROM    reviews
                              WHERE   reviews.book_id = books.id)
GROUP BY books.id
要将其转换为ActiveRecord,我将执行以下操作:

class Book
  scope :recently_reviewed, joins(:reviews)
    .where('reviews.created_on = (SELECT MAX(books.created_at) FROM reviews WHERE reviews.book_id = books.id)')
    .group('books.id')
end
Book.recently_reviewed
然后,通过执行以下操作,您可以获得所有上次审阅的书籍的列表:

class Book
  scope :recently_reviewed, joins(:reviews)
    .where('reviews.created_on = (SELECT MAX(books.created_at) FROM reviews WHERE reviews.book_id = books.id)')
    .group('books.id')
end
Book.recently_reviewed
然后,您可以通过

Book.recently_reviewed.limit(n)
你试过这个吗

def self.recently_reviewed
  Review.preload(:book).order(created_at: :desc).limit(5).map(&:book)
end
你试过这个吗

def self.recently_reviewed
  Review.preload(:book).order(created_at: :desc).limit(5).map(&:book)
end

如果您的关联设置正确,为什么不查找最后n篇评论的Book.title?如果您的关联设置正确,为什么不查找最后n篇评论的Book.title?