MongoDb如何按字符串按月和年分组

Ram*_*esh 4 mongodb mongodb-query aggregation-framework

我正在收集字段dateStr

  {  ....    "dateStr" : "07/01/2020" .... }
  {  ....    "dateStr" : "07/01/1970"   .... }
Run Code Online (Sandbox Code Playgroud)

我想从dateStr字段按月和年分组

我试过了

    db.collection.aggregate( 
       {$project : { 
              month : {$month : new Date("$dateStr")}, 
              year : {$year :  new Date("$dateStr")}
          }}, 
        {$group : { 
                _id : {month : "$month" ,year : "$year" },  
              count : {$sum : 1} 
        }})
Run Code Online (Sandbox Code Playgroud)

输出:

{
"result" : [ 
        {
            "_id" : {
                "month" : 1,
                "year" : 1970
            },
            "count" : 2
        }
    ],
    "ok" : 1
}
Run Code Online (Sandbox Code Playgroud)

但我有两年1970,2020.为什么我会获得单曲?

Nei*_*unn 7

您不能在对象本身的任何其他内容上使用日期聚合运算符Date.您最终的最佳选择是将这些"字符串"转换为正确的Date对象,以便您可以在此操作和将来的操作中正确查询.

也就是说,如果你的"字符串"总是有一个共同的结构,那么有一种方法可以使用聚合框架工具.它需要大量的操作思想,这不会使这成为处理问题的"最佳"方法.但是通过设置"双位数"结构和一致的分隔符,这可以通过$substr运算符实现:

db.collection.aggregate([
   { "$group": {
       "_id": {
           "year": { "$substr": [ "$dateStr", 7, 4 ] },
           "month": { "$substr": [ "$dateStr", 4, 2 ] }
       },
       "count": { "$sum": 1 }
   }}
])
Run Code Online (Sandbox Code Playgroud)

因此JavaScript转换在聚合框架内不起作用.您始终可以根据"客户端代码"评估将输入"提供"到管道,但聚合过程本身不会评估任何代码.就像基本的查询引擎一样,这都是基于"数据结构"实现,它使用"本机操作符"指令来完成工作.

您无法将字符串转换为聚合管道中的日期.您应该使用真实BSON Date对象,但如果存在一个可以在"词法顺序"中呈现的一致格式,则可以使用字符串.

我仍然建议您BSON Dates尽快将这些转换为ASAP.请注意,"ISODate"或UTC值是使用不同的字符串形式构造的.即:

new Date("2020-01-07")
Run Code Online (Sandbox Code Playgroud)

采用"yyyy-mm-dd"格式.至少对于JavaScript调用.