如何在查询中按最新的嵌套模型created_at排序

时间:2018-10-08 15:07:50

标签: ruby postgresql activerecord ruby-on-rails-5

我有一个问题,我不知道这是否可行,但是假设这些模型

class Event < ApplicationRecord
  has_many :gifs
end

class Gif < ApplicationRecord
  belongs_to :event
end
使用rails console

空白数据库

gif_1 = Gif.create
gif_2 = Gif.create
gif_3 = Gif.create
event_1 = Event.new
event_1.gifs = [gif_1, gif_3]
event_1.save
event_2 = Event.new
event_2.gifs = [gif_2]
event_2.save

您如何通过事件的最后创建的gif属性created_at对事件进行排序。

这是我尝试过的示例,但未产生正确的结果

ordered_events = Event.includes(:gifs).joins(:gifs).order("gifs.created_at DESC")
ordered_events.first.id
=> 2 # I want this to return 1

现在我明白了为什么我的尝试可能没有用。我认为是因为它可能只查看了第一个Gif才能进行排序。

最重要的是,我还有一个想法,在这里我不知道从哪里开始尝试执行查询,但是从我写的内容来看,如果Event的值为0 Gif,该怎么办?似乎没有gif会将这些事件仅归于那些确实具有gif的事件,但这对我不起作用。

这是rails console中的另一个上下文,它比较实际,因为通常您首先需要一个事件来存储Gif

event_1 = Event.create
event_2 = Event.create
gif_1 = Gif.create(event_id: event_1.id)
gif_2 = Gif.create(event_id: event_2.id)
event_1 = Event.create
gif_3 = Gif.create(event_id: event_1.id)

现在,我想从查询中得到的是某种[event_1, event_3, event_2],因为既然event_3没有GIF,我想用他的created_at来订购。

我知道如何通过一些辅助功能或其他功能手动完成此操作,但我真的很希望能够在一个查询中直接进行这种操作。

1 个答案:

答案 0 :(得分:0)

例如:

Event.joins(:gifs)
     .group('events.id')
     .order('MAX(gifs.created_at) DESC')

此查询采用events,将其与gifs结合,按event.id分组(以消除事件重复,以防一个事件包含多个gif的事件),并按最新(最大){ {1}}事件的Gif时间,以降序排列。

由于它使用了created_at方法,在SQL查询中将其解包为joins,因此该查询不会返回没有gif的事件。要解决此问题,请使用INNER JOIN

left_outer_joins