MongoDB获取当前日期的文档

时间:2016-03-09 07:09:56

标签: mongodb mongodb-query aggregation-framework

我有一个如下文档,现在我想按频道,年份和月份以及日期分组,然后我想选择当前日期的记录。这是我的文件:

{
    "_id" : ObjectId("56de5eab29f9463baf6eb7d2"),
    "created_at" : ISODate("2016-03-08T05:10:03.854Z"),
    "updated_at" : ISODate("2016-03-08T05:10:03.854Z"),
    "channel" : "040403",
    "countrycode" : "IN",
    "distinctid" :       "abc123456",   
    "os" : "Android"
}

我写了这样的聚合:

db.collection.aggregate([
    {$project: {              
              "channel":"$channel",
              "year": {$year: "$created_at" },
              "month: {$month: "$created_at" },
              "day": {$dayOfMonth: "$created_at" }
         },
         {$match: {
             "year": new Date().getFullYear(),
             "month": new Date().getMonth() + 1, 
             "day": new Date().getDate()     
         },         
         {$group:
             {{"_id":{"channel":"$channel",
                       year: {$year: "$created_at" },
                       month: {$month: "$created_at" },
                       day: {$dayOfMonth: "$created_at" }},
              "count":{"$sum":1}
             }
          }
    ]
)

然而,它说

  

缺失:属性id @(shell)之后:1:108

这是我的想法是正确的,为什么语法错了? 感谢

2 个答案:

答案 0 :(得分:1)

取消初始$project并使用$match上的“范围”代替:

  // Get current start of day and start of tomorrow
  var now = Date.now(),
      oneDay = ( 1000 * 60 * 60 * 24 ),
      today = new Date( now - ( now % oneDay ) ),
      tomorrow = new Date( today.valueOf() + oneDay );

  db.collection.aggregate([
     // Match on range
     { "$match": {
         "$created_at": {
            "$gte": today, "$lt": tomorrow
         }
     }},
     // Then group on just the rolled up date
     { "$group": {
         "_id":{
             "channel":"$channel",
             "year": { "$year": "$created_at" },
             "month": { "$month": "$created_at" },
             "day": { "$dayOfMonth": "$created_at" }
          },
          "count":{"$sum":1}
     }}
  ])

使用$gte$lt的“范围”是最有效的选择。如果您尝试首先使用$project提取组件,那么这实际上是通过所有数据“完全通过”来计算这些值。只有在完成所有工作后才能实际选择所需的文件。

$match是第一阶段时,所有过滤都已完成,留下的文档更少,结果更快。更重要的是,作为一个“查询”,在初始阶段,这是唯一的机会你的处理必须使用“索引”来加快速度。所以最好抓住这个机会。

并不是说每天只有一天选择时,每天的分组确实为你做了什么,但是当你需要一系列日期时,它总是技术。是的,“单一”日仍然一个“范围”。

至于你试过的是什么问题?很多事情,但最明显的是在第一阶段没有使用$match

您真正需要记住的其他事情是$project$group等“输出”来自源的文档的更改表示。因此,“out”出现的是后续“管道”阶段可用的所有内容,依此类推。认为“unix pipe”|带有命令,并且最好类比了解每个管道阶段与另一个管道阶段的关系。即:

ps -ef | grep mongo | tee output.txt

答案 1 :(得分:0)

您的查询存在两个问题:

  1. 每个阶段你都会错过很多关闭}
  2. 您按Integer类型(year类型(monthday$year)的字段进行分组,但您应用了聚合运算符($month,{期待$day字段的{1}},Date}。
  3. 请尝试此查询:

    db.collection.aggregate([{
        $project: {
            "channel": "$channel",
            "year": { $year: "$created_at" },
            "month": { $month: "$created_at" },
            "day": { $dayOfMonth: "$created_at" }
        }
    }, {
        $match: {
            "year": new Date().getFullYear(),
            "month": new Date().getMonth() + 1,
            "day": new Date().getDate()
        }
    }, {
        $group: {
            "_id": { "channel": "$channel", year: "$year", month: "$month", day: "$day" },
            "count": { "$sum": 1 }
        }
    }]);