Active Record Rails 4对集合的唯一查询

时间:2014-05-14 19:15:14

标签: ruby-on-rails activerecord

我的用户有很多'received_messages'和'sent_messages'(来自只包含receiver_id,sender_id和内容的连接表)。我的关联都设置正确,当我调用user.received_messages和user.sent_messages时,我返回了正确的集合。我现在要做的是过滤返回的消息集合,这样它们只会返回每个唯一发送者(如果是received_messages)或接收者(如果是sent_messages)的第一条(最新的)消息。

我试过了:

@sent_messages = @user.sent_messages.uniq(&:receiver_id) @sent_messages = @user.sent_messages.select(:receiver_id).distinct 等等但这会让我回到一个数字而不是实际的集合。

不确定这是否相关,但在我的用户模型中,关联设置为:

has_many :received_messages, class_name: 'Message', foreign_key: 'receiver_id', table_name: 'messages' has_many :sent_messages, class_name: 'Message', foreign_key: 'sender_id', table_name: 'messages'

并在消息模型中:

belongs_to :sender, foreign_key: 'sender_id', class_name: "User" belongs_to :receiver, foreign_key: 'receiver_id', class_name: "User"

3 个答案:

答案 0 :(得分:2)

试试这个:

message_per_uniq_receiver = @user.sent_messages.select('DISTINCT ON (receiver_id) *')
                                               .order('receiver_id, messages.created_at DESC')

message_per_uniq_sender = @user.received_messages.select('DISTINCT ON (sender_id) *')
                                                 .order('sender_id, messages.created_at DESC')

DISTINCT ON有点复杂(documentation here):

长话短说,DISTINCT ON(sender_id)将为在消息表中找到的每个不同的sender_id创建组,并将选择每个组中的第一个,该组的第一个由{{确定1}}子句。

答案 1 :(得分:0)

"选择"方法类似于SQL中的SELECT命令。它选择一个数据库列并返回数据。

因此,sent_messages.select(:receiver_id)返回接收者ID,这是一个整数。

如果您希望sent_messages具有特定的接收者ID,请使用"其中"方法。

例如,sent_messages.where(receiver_id: some_receiver_id)

答案 2 :(得分:0)

从您的不同接收者ID列表开始。称之为receiver_id_list。然后迭代它们。对于每个ID,找到属于该接收器的最新消息,并将其添加到阵列中。

most_recent_sent_messages = []

receiver_id_list.each do |id|
  most_recent_sent_messages << @user.sent_messages.where(receiver_id: id).order(time_sent: :desc).first
end

最高time_sent(或任何你命名的时间戳)应该是最新的消息,这就是你应该按降序对它们进行排序的原因。