如何根据从 objectId 中提取的创建日期对 MongoDB 集合进行分组?

Sim*_*one 5 timestamp mongodb aggregation-framework

我想在 mongoDB 中使用组聚合,以便根据创建日期对我的文档进行分组。我没有将创建日期保存为字段,但我知道我可以从我的 ObjectId 中提取这个日期。所以,我试着写这样的东西:

db.sales.aggregate(
   [
      {
        $group : {
           _id : { month: {$month: ObjectId("$_id").getTimestamp()}, 
                   day: {$dayOfMonth: ObjectId("$_id").getTimestamp()}, 
                   year: {$year: ObjectId("$_id").getTimestamp()}
           },
           averageQuantity: { $avg: "$quantity" },
           count: { $sum: 1 }
        }
      }
   ]
)
Run Code Online (Sandbox Code Playgroud)

我收到此错误:错误:无效对象 ID:长度:@(shell):5:37

当我写一个特殊的 ObjectId 而不是“$_id”时,它起作用了。例如: ObjectId("507c7f79bcf86cd7994f6c0e").getTimestamp()

它也可以工作,当我有一个日期字段在其中存储我的创建日期并写入如下内容时:

db.sales.aggregate(
   [
      {
        $group : {
           _id : { month: {$month: "$date"}, 
                   day: {$dayOfMonth: "$date"}, 
                   year: {$year: "$date"}
           },
           averageQuantity: { $avg: "$quantity" },
           count: { $sum: 1 }
        }
      }
   ]
)
Run Code Online (Sandbox Code Playgroud)

但我想知道,我怎样才能直接使用我的 ObjectId 并获取时间戳。

聚合分组及其相关数据可在此链接上找到:https : //docs.mongodb.com/manual/reference/operator/aggregation/group/

但是我用我的自动 mongoDB 生成的 id 替换了这个例子的简单整数 id 。

Cle*_*ath 1

getTimestamp() 是一个函数,应该在 javascript 函数中使用。

您需要在查询中更正两件事。一种是检索 Id,另一种是使用 getTimestamp() 函数。

检索 ID

_id : { month: {$month: ObjectId("$_id").getTimestamp()}, 
                   day: {$dayOfMonth: ObjectId("$_id").getTimestamp()}, 
                   year: {$year: ObjectId("$_id").getTimestamp()}
      }
Run Code Online (Sandbox Code Playgroud)

使用月、日和年检索 id 的正确方法

_id : { month: "$_id.month",  day: "$_id.day", year: "$_id.year"},
Run Code Online (Sandbox Code Playgroud)

原因:

月份是文档 ID 的一部分,因此必须以这种方式检索它。类似的日期和年份。

获取时间戳

将结果放入 JavaScript 循环中并使用 getTimestamp() 方法。

db.sales.aggregate(
   [
      {
        $group : {
           _id : { month: "$_id.month",  day: "$_id.day", year: "$_id.year"},
           averageQuantity: { $avg: "$quantity" },
           count: { $sum: 1 }
        }
      }
   ]
).forEach(function (doc) 
    {
     doc["doc._id.month"]=doc._id.month.getTimestamp();
     doc["doc._id.day"]=doc._id.day.getTimestamp();
     doc["doc._id.year"]=doc._id.year.getTimestamp();
     printjson(doc);
    });
Run Code Online (Sandbox Code Playgroud)

如果你有这样的收藏

{
        "_id" : {
                "month" : ObjectId("57bd7d3c0da65e3f92328e50"),
                "day" : ObjectId("57bd7d3c0da65e3f92328e51"),
                "year" : ObjectId("57bd7d3c0da65e3f92328e52")
        },
        "quantity" : 200
}
Run Code Online (Sandbox Code Playgroud)

使用 javascript 函数执行聚合查询后的结果将给出以下结果

{
        "_id" : {
                "month" : ObjectId("57bd7d3c0da65e3f92328e50"),
                "day" : ObjectId("57bd7d3c0da65e3f92328e51"),
                "year" : ObjectId("57bd7d3c0da65e3f92328e52")
        },
        "averageQuantity" : 200,
        "count" : 1,
        "doc._id.month" : ISODate("2016-08-24T10:55:56Z"),
        "doc._id.day" : ISODate("2016-08-24T10:55:56Z"),
        "doc._id.year" : ISODate("2016-08-24T10:55:56Z")
}
Run Code Online (Sandbox Code Playgroud)