简体   繁体   English

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

[英]Active Record Rails 4 Unique Query on Collection

My users have many 'received_messages' and 'sent_messages' (from a join table that just contains a receiver_id, sender_id, and the content). 我的用户有很多“ received_messages”和“ sent_messages”(来自仅包含了receive_id,sender_id和内容的联接表)。 My associations are all set up correctly and when I call user.received_messages and user.sent_messages I am returned the correct collections. 我的关联都正确设置,当我调用user.received_messages和user.sent_messages时,我将获得正确的集合。 What I am now trying to do is filter the returned message collections so they will only return the first(newest) message from each unique sender(if it is received_messages) or receiver(if it is sent_messages). 我现在想做的是过滤返回的消息集合,这样它们将仅从每个唯一发件人(如果是receive_messages)或接收者(如果是send_messages)返回第一(最新)消息。

I have tried : 我努力了 :

@sent_messages = @user.sent_messages.uniq(&:receiver_id) @sent_messages = @user.sent_messages.select(:receiver_id).distinct Etc but this keeps returning to me an array of numbers rather than actual collections. @sent_messages = @user.sent_messages.uniq(&:receiver_id) @sent_messages = @user.sent_messages.select(:receiver_id).distinct等等,但这总是向我返回一组数字,而不是实际的数字。

Not sure if this is relevant but in my User model the associations are set up as : 不确定是否相关,但是在我的用户模型中,关联设置为:

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'

and in the Message model: 在消息模型中:

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

Try this: 尝试这个:

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')

This DISTINCT ON is kinda complex ( documentation here ): DISTINCT ON有点复杂( 此处的文档 ):

Long story short, the DISTINCT ON(sender_id) will create groups for each distinct sender_id found in the messages table, and will select the first of each group, the first of the group is determined by the ORDER BY clause. 长话短说, DISTINCT ON(sender_id)将为在消息表中找到的每个不同的sender_id创建组,并将选择每个组的第一个,该组的第一个由ORDER BY子句确定。

The "select" method is like the SELECT command in SQL. “选择”方法类似于SQL中的SELECT命令。 It selects a database column and returns data. 它选择一个数据库列并返回数据。

Thus, sent_messages.select(:receiver_id) returns the receiver ID, which is an integer. 因此, sent_messages.select(:receiver_id)返回接收者ID,它是一个整数。

If you want sent_messages with a particular receiver ID, use the "where" method. 如果希望send_messages具有特定的接收者ID,请使用“ where”方法。

For example, sent_messages.where(receiver_id: some_receiver_id) . 例如, sent_messages.where(receiver_id: some_receiver_id)

Start with your list of distinct receiver ID's. 从您的不同接收者ID列表开始。 Call it receiver_id_list. 称它为receive_id_list。 Then iterate through them. 然后遍历它们。 For each ID, find the newest message belonging to that receiver, and add it to an array. 对于每个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

The highest time_sent (or whatever you named the timestamp) should be the newest message, which is why you should sort them in descending order. 最高的time_sent (或称为timestamp的名称)应该是最新的消息,这就是为什么您应该按降序对它们进行排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM