在mongoDb中分组,不计算在内

时间:2012-09-07 08:23:54

标签: mongodb date group-by

我正在开展一个个人项目,在这个项目中我需要通过舍入日期将所有对象分组到同一小时。问题是我不想把事情搞砸。

我在mongodb中使用以下格式存储数据

{ 
   "_id" : ObjectId("4d663451d1e7242c4b68e000"), 
   "date" : "Mon Dec 27 2010 18:23:22 GMT+0000 (UTC)", 
   "name" : "james"
}, { 
    "_id" : ObjectId("4d6634514cb5cb2c4b69e000"), 
    "date" : "Mon Dec 27 2010 18:47:53 GMT+0000 (UTC)", 
    "name" : "bond", 
}, { 
    "_id" : ObjectId("4d6634514cb5cb2c4b69e000"), 
    "date" : "Mon Dec 27 2010 21:51:23 GMT+0000 (UTC)", 
    "name" : "bruce", 
}

我正在寻找以下格式的结果

{
   "rounded_date" : "Mon Dec 27 2010 18:00:00 GMT+0000 (UTC)",
   "items" : [ { 
           "_id" : ObjectId("4d663451d1e7242c4b68e000"), 
           "date" : "Mon Dec 27 2010 18:23:22 GMT+0000 (UTC)", 
           "name" : "james"
       }, { 
           "_id" : ObjectId("4d6634514cb5cb2c4b69e000"), 
           "date" : "Mon Dec 27 2010 18:47:53 GMT+0000 (UTC)", 
           "name" : "bond", 
       }
   ]
}, {
    "rounded_date": Mon Dec 27 2010 21:00:00 GMT+0000 (UTC),
    "items" : [ { 
            "_id" : ObjectId("4d6634514cb5cb2c4b69e000"), 
            "date" : "Mon Dec 27 2010 21:51:23 GMT+0000 (UTC)", 
            "name" : "bruce", 
        }
    ]
}

谢谢你的帮助。

2 个答案:

答案 0 :(得分:4)

这似乎是aggregation framework(mongoDB 2.2中的新功能)的一个很好的候选者,唯一需要注意的是你现在无法动态创建新日期,但是你可以从日期和时间中提取所需的数据。由它组成。

请参阅以下示例:

# Load the sample data
db.datetest.save({ 
   "_id" : ObjectId("4d663451d1e7242c4b68e000"), 
   "date" : ISODate("2010-12-27T18:23:22Z"),
   "name" : "james"
});

db.datetest.save({ 
    "_id" : ObjectId("4d6634514cb5cb2c4b69e000"), 
    "date" : ISODate("2010-12-27T18:47:53Z"),
    "name" : "bond", 
});

db.datetest.save({ 
    "_id" : ObjectId("4d6634514cb5cb2c4b69e001"), 
    "date" : ISODate("2010-12-27T21:51:23Z"),
    "name" : "bruce", 
});

现在执行聚合 - 首先将文档重新投影到有用的格式。

db.datetest.aggregate(
    {$project: {
        hour: {0: {"$year": "$date"},
               1: {"$month": "$date"},
               2: {"$dayOfMonth": "$date"},
               3: {"$hour": "$date"}},
        item: {
            _id: "$_id",
            date: "$date",
            name: "$name"
        }
    }},
    {$group: {
        _id: "$hour",
        items: {$push: "$item"}
    }}
)

聚合解释:

  1. 这里我们创建一个hour子文档,其中包含从日期中提取的年,月,日和小时。我们还创建了一个item子文档,我们将在该组中使用。
  2. hour分组,并将所有item个文档推送到items数组。
  3. 结果如下:

    {
      "result" : [{
        "_id" : { "0" : 2010, "1" : 12, "2" : 27, "3" : 21 },
        "items" : [
          {
            "date" : ISODate("2010-12-27T21:51:23Z"),
            "name" : "bruce"
          }
        ]}, {
        "_id" : {"0" : 2010, "1" : 12, "2" : 27, "3" : 18},
        "items" : [{
            "date" : ISODate("2010-12-27T18:23:22Z"),
            "name" : "james"
          }, {
            "date" : ISODate("2010-12-27T18:47:53Z"),
            "name" : "bond"
          }
        ]}
      ],
      "ok" : 1
    }
    

答案 1 :(得分:0)

我找到了另一个解决方案:

db.collection.group({
    cond: {'public': true},
    keyf: function(doc) {
        var date = doc.when
        date.setMinutes(0,0,0);
        return {'date' : date};
    },
    initial: { items:[] },
    reduce: function(doc, out) { out.items.push(doc); }
});

事情是在使用groupby之后不可能对某些内容进行排序。我想我必须在客户端这样做。