2

我有一个包含以下字段的消息集合:_idsenderIdreceiverIddateSubmittedMsmessage,对于给定的用户,我想将所有其他用户的最新消息返回给他。因此,例如,如果有用户 Alex、Barb、Chuck、Dora,我想返回 Alex 与 Barb、Chuck 和 Dora 之间的最新消息。做这个的最好方式是什么?我可以使用聚合一步完成吗?

官方在线文档(http://docs.mongodb.org/manual/reference/aggregation/min/)中的聚合示例显示了如何找到集合中各组的最低年龄,但我需要的是类似于 find一群人中最年轻的人的名字。

这是我目前的方法:

dateSubmitted第 1 步:找出Alex 发送和接收的所有消息的最高值,对其他用户进行分组:

var M = Messages.aggregate(
{$match: 
    {$or: [{senderId: 'Alex'}, {receiverId: 'Alex'}]}
}, 
{$group: {_id: "$receiverId", lastestSubmitted: {$max: "$submitted"} }}).fetch();

第 2 步:创建一个包含这些最高 dateSubmitted 值的数组:

var MIds = _.pluck(M,'lastestSubmitted');

第 3 步:按 senderId、receiverId 和 latestSubmitted 查找这些消息:

return Messages.find(
    {submitted: {$in: MIds}, $or: [{senderId: 'Alex'}, {receiverId: 'Alex'}]},
    {$sort: {submitted: 1}}
});

这有两个问题:

  1. 可以一步完成而不是三步吗?也许通过 mapReduce 或 Aggregate 命令?
  2. receiverId: 'Alex'有没有一种方法可以对以下内容进行分组,而不是仅在 上进行分组: $or [{receiverId: 'Alex', senderId: 'Barb'}, {senderId: 'Alex', receiverId: 'Barb'}]?(但对于其他每个用户)这将允许我在 Alex 与之交谈的任何两个参与者之间的对话中获得最新消息。例如:

有什么建议么?

4

1 回答 1

1

您唯一需要更改的是分组阶段中的 group._id 。虽然您可以为此提议使用文档,而不仅仅是一个字段,但您可以在同一管道中应用排序。但是,如果您仅使用 receiverId 进行分组,则不会更改。

var M = Messages.aggregate(
{$match: 
    {$or: [{senderId: 'Alex'}, {receiverId: 'Alex'}]}
}, 
{$group: 
    {_id: {
          receiverId: "$receiverId", 
          senderId: "$senderId"}, 
      lastestSubmitted: {$max: "$submitted"} }
 },
 {$sort: {submitted: -1}
 },
 {$limit: 1}
 ).fetch();

上面的这个例子只增加了检查第二个最近被 ping 的连接或第三个连接的可能性,如果你只可能得到你甚至不需要分组的最新消息。运行这个:

var M = Messages.aggregate(
{$match: 
    {$or: [{senderId: 'Alex'}, {receiverId: 'Alex'}]}
}, 
 {$sort: {submitted: -1}
 },
 {$limit: 1}
 ).fetch();

上面的答案是获取单个用户和其他人之间的最新消息,以获取涉及用户的所有对之间的最新消息阅读下>>>

根据评论,我误解了这个问题,但上面的部分无论如何都是有用的。您的问题的正确解决方案如下。在这种情况下,困难在于获得用于分组的密钥并识别切换的对(bob -> tom == tom -> bob)。你可以使用条件和排序来识别掉期。(这当然是一个更困难的问题)代码如下所示:

var M = Messages.aggregate(
{$match: 
    {$or: [{senderId: 'Alex'}, {receiverId: 'Alex'}]}
},
{$project:
    {'part1':{$cond:[{$gt:['$senderId','$receiverId']},'$senderId','$receiverId']},
     'part2':{$cond:[{$gt:['$senderId','$receiverId']},'$receiverId','$senderId']},
     'message':1,
     'submitted':1
    }
},
{$sort: {submitted: -1}},
{$group: 
    {_id: {
          part1: "$part1", 
          part2: "$part2"}, 
      lastestSubmitted: {$first: "$submitted"},
      message: {$first: "$message"} }
 }
 ).fetch();

如果您不熟悉上面使用的某些运算符,例如 $cond 或 $first,请查看

于 2013-10-01T13:48:35.087 回答