返回每个最后一个文档以获取公共ID

时间:2017-08-08 03:54:08

标签: mongodb mongoose mongodb-query aggregation-framework

我有一个messages集合。执行

Message.find({}).sort({ created_at: -1 }).exec((err, msg) => {}

按日期返回所有文档(最新文档首先返回)。每个messages文档都包含conversations ID。以下是此查询返回的简短示例:

[ { _id: 59867e2fba6aa11b3ea7142a,
    message: 'Fourth message.',
    created_at: 2017-08-06T02:25:51.589Z,
    unread: true,
    __v: 1,
    conversations: [ 59867c2c3853621b294b394f ] },
  { _id: 59867dd7ba6aa11b3ea71429,
    message: 'Second message.',
    created_at: 2017-08-06T02:24:23.888Z,
    unread: false,
    __v: 1,
    conversations: [ 59867dbcba6aa11b3ea71427 ] },
{ _id: 59867dbcba6aa11b3ea71428,
    message: 'First message.',
    created_at: 2017-08-06T02:23:56.480Z,
    unread: false,
    __v: 1,
    conversations: [ 59867dbcba6aa11b3ea71427 ] } ]

多条消息属于单个对话(例如此处的最后两个消息文档)。因此,会话ID 59867dbcba6aa11b3ea71427会多次出现。

我想为每个会话返回第一个消息文档。因此,'Fourth message.'将被退回,'Second message.'也会被退回,因为它们是不同对话的一部分。

但是,不应该返回'First message.',因为它与'Second message.'相同,但它们都是对话ID 59867dbcba6aa11b3ea71427的一部分。

我如何做到这一点?

1 个答案:

答案 0 :(得分:1)

不确定为什么"conversations"在这里是一个数组,但你要求的是" last"每个"分组边界"的项目,即"conversations"值。这使用聚合来获得:

Message.aggregate([
  { "$unwind": "$conversations" },
  { "$sort": { "conversations": 1 , "created_at": -1 } },
  { "$group": {
    "_id": "$conversations",
    "doc": { "$first": "$$ROOT" }
  }},
  { "$sort": { "doc.created_at": -1 } }
],(err,messages) => {
  if (err) throw err;
  console.log(messages);
})

哪会回来:

[{
   _id: 59867c2c3853621b294b394f,
   doc: { _id: 59867e2fba6aa11b3ea7142a,
      message: 'Fourth message.',
      created_at: 2017-08-06T02:25:51.589Z,
      unread: true,
      __v: 1,
      conversations: 59867c2c3853621b294b394f }},
  { _id: 59867dbcba6aa11b3ea71427,
    doc: _id: 59867dd7ba6aa11b3ea71429,
      message: 'Second message.',
      created_at: 2017-08-06T02:24:23.888Z,
      unread: false,
      __v: 1,
      conversations: 59867dbcba6aa11b3ea71427 }}]

所以$unwind是处理"数组"内容,因为我们将分组"在那个价值上。 $sort将项目置于" order"对话和"createdAt"日期在"降序"`与最新文件"第一"对于每次谈话。

由于文档是以这种方式排序的,因此在按"conversation"每个AbT5xY\s*Apple值应用$first时,您会使用$group

或者你可以"反向"排序顺序并使用$last来收集,但这一切都取决于预期的结果顺序。