按最新时间戳聚合mongodb

时间:2015-04-21 12:43:51

标签: node.js mongodb

我希望使用聚合功能获取每个城市上一个时间戳的“人口”。

在像这样的MongoDB中:

{
  "_id": {"$oid": "55354bc97b5dfd021f2be661"},
  "timestamp": {"$date": "2015-04-20T18:56:09.000Z"},
  "city": "Roma",
  "population": [
    {"age": 90,"count": 1000},
    {"age": 25,"count": 25}
  ]
},
{
  "_id": {"$oid": "55354c357b5dfd021f2be663"},
  "timestamp": {"$date": "2015-04-20T18:57:57.000Z"},
  "city": "Madrid",
  "population": [
    {"age": 90,"count": 10},
    {"age": 75,"count": 2343},
    {"age": 50,"count": 500},
    {"age": 70,"count": 5000}
  ]
},
{
  "_id": {"$oid": "55362da541c37aef07d4ea9a"},
  "timestamp": {"$date": "2015-04-21T10:59:49.000Z"},
  "city": "Roma",
  "population": [
    {"age": 90,"count": 5}
  ]
}

我想要检索所有城市,但每个城市只有最新的时间戳:

{
  "city": "Roma",
  "population": [
    {"age": 90,"count": 5}
  ]
},
{
  "city": "Madrid",
  "population": [
    {"age": 90,"count": 10},
    {"age": 75,"count": 2343},
    {"age": 50,"count": 500},
    {"age": 70,"count": 5000}
  ]
}

我尝试了类似this answer的内容,但在获取每个城市的最新时间戳后,我不知道如何“解开”人群:

db.collection('population').aggregate([
  { $unwind: '$population' },
  { $group: { _id: '$city', timestamp: { $max: '$timestamp' } } },
  { $sort: { _id : -1 } }
  ], function(err, results) {
    res.send(results)
});

2 个答案:

答案 0 :(得分:1)

以下聚合管道将为您提供所需的结果。管道中的第一步按timestamp字段(降序)对文档进行排序,然后在下一个$group阶段按city字段对有序文档进行分组。在$group运算符中,您可以通过$$ROOT运算符提取population数组字段。 $first运算符返回将$$ROOT表达式应用于共享相同city键的一组文档中的第一个文档所产生的值。最后的管道阶段涉及将前一个管道中的字段投影到所需的字段中:

db.population.aggregate([      
    {
        "$sort": { "timestamp": -1 }
    },
    { 
      "$group": { 
          "_id": "$city",          
          "doc": { "$first": "$$ROOT" }
       } 
    },
    {
        "$project": { 
          "_id": 0, 
          "city": "$_id",
          "population": "$doc.population"
       }
    }       
]);

<强>输出

/* 0 */
{
    "result" : [ 
        {
            "city" : "Madrid",
            "population" : [ 
                {
                    "age" : 90,
                    "count" : 10
                }, 
                {
                    "age" : 75,
                    "count" : 2343
                }, 
                {
                    "age" : 50,
                    "count" : 500
                }, 
                {
                    "age" : 70,
                    "count" : 5000
                }
            ]
        }, 
        {
            "city" : "Roma",
            "population" : [ 
                {
                    "age" : 90,
                    "count" : 5
                }
            ]
        }
    ],
    "ok" : 1
}

答案 1 :(得分:0)

我认为您要使用$project代替$unwind

db.collection('population').aggregate([{
     $group: {
       _id: '$city',
       timestamp: {$max: '$timestamp'}
     }
  }, {
     $project: {
       population: '$doc.population'
     }
  }, {
    $sort: {
      _id : -1
  }
}], function(err, results) {
  res.send(results)
});