mongodb / meteor:如何获取对应于另一个字段的$ max值的一个字段的值?

时间:2013-09-30 22:59:57

标签: mongodb meteor

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

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

这是我目前的做法:

步骤1:查找Alex发送和接收的所有邮件的dateSubmitted的最高值,并对其他用户进行分组:

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与之交谈的任何两个参与者之间的对话中获取最新消息。例如:
  3. 有什么建议吗?

1 个答案:

答案 0 :(得分: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,请查看this