Mongo:当查询还有$ groupy时,在$ match子句中使用$ dayOfWeek

时间:2013-06-21 17:19:57

标签: mongodb group-by match dayofweek

我有一个mongo文档,其中一些寄存器以日期存储,例如以非常简单的方式存储:

{
    "vehicleId" : "vehicle4",
    "telemetryDate" : ISODate("2013-06-22T05:00:00Z"),
    "alarmsTotal" : 9
}
{
    "vehicleId" : "vehicle5",
    "telemetryDate" : ISODate("2013-06-20T05:00:00Z"),
    "alarmsTotal" : 2
}

我需要通过vhicleId执行一个组,总计警报总数。不过,可以选择是否排除周末(周六,周日)。

我一直在寻找与Mongo这个问题无关的答案。我的查询,如果没有将排除周末纳入正常工作的帐户是:

{
   "aggregate":"telemetrySummary",
   "pipeline":[
      {
         "$match":{
            "telemetryDate":{
               "$gte":{
                  "$date":"2013-06-20T05:00:00.000Z"
               },
               "$lte":{
                  "$date":"2013-06-24T05:00:00.000Z"
               }
            }
         }
      },
      {
         "$group":{
            "_id":{
               "vehicleId":"$vehicleId"
            },
            "alarms":{
               "$sum":"$alarmsTotal"
            }
         }
      }
   ]
}

我需要排除mongo运算符$ dayOfWeek为1(星期日)和7(星期日)的值。我尝试了很多查询,其中一个逻辑是:

{
   "aggregate":"telemetrySummary",
   "pipeline":[
      {
         "$match":{
            "telemetryDate":{
               "$gte":{
                  "$date":"2013-06-20T05:00:00.000Z"
               },
               "$lte":{
                  "$date":"2013-06-24T05:00:00.000Z"
               }
            },
            "{ \"$dayOfWeek\" : \"$telemetryDate\"}":{
               "$in":[2,3,4,5,6]
            }
         }
      },
      {
         "$group":{
            "_id":{
               "vehicleId":"$vehicleId"
            },
            "alarms":{
               "$sum":"$alarmsTotal"
            }
         }
      }
   ]
}

我认为我的真正问题基本上是我不知道如何将$ dayOfWeek操作存储在非grupable变量上作为telemetryDate到day变量中,我可以与$ in运算符进行比较。

感谢阅读并希望找到一些指导:)

2 个答案:

答案 0 :(得分:3)

实际上这很简单 - 您可以使用$ project创建原始文档中不存在的新字段 - 您可以计算新值,也可以有条件地投影不同的值,具体取决于原始值。您甚至可以在单个组阶段计算总报警以及工作日仅报警。

以下是您在项目阶段需要做的事情:

{"$project" : {
        "vehicleId" : 1,
        "telemetryDate" : 1,
        "alarmsTotal" : 1,
        "alarmsWeekdays" : {
            "$cond" : [
                {
                    "$or" : [
                        {
                            "$eq" : [
                                {
                                    "$dayOfWeek" : "$telemetryDate"
                                },
                                1
                            ]
                        },
                        {
                            "$eq" : [
                                {
                                    "$dayOfWeek" : "$telemetryDate"
                                },
                                7
                            ]
                        }
                    ]
                },
                0,
                "$alarmsTotal"
            ]
        }
    }
}

上面说的是:“通过这三个领域,但也计算一个新的领域报警周末如此:......”

更多“英语”术语的实际表达恰好是:

IF `$dayOfWeek` of telemetryDate is equal to 1 
OR `$dayOfWeek` of telemetryDate is equal to 7
THEN `$project` the value 0 as `alarmsWeekdays
ELSE `$project` the value from `$alarmsTotal` as `alarmsWeekdays`

答案 1 :(得分:2)

您应该在 $ project 中使用 $ dayOfWeek ,如下所示:

[{<your match by date>}, {$project:{vehicleId:1, telemetryDate:1, alarmsTotal:1, dow:{$dayOfWeek:'$telemetryDate'}}}, {$match:{dow:{$in:[2,3,4,5,6]}}}, <rest of pipeline> ]

btw ,您的第一个 $ match 可以从使用索引中受益,就像普通的查找命令一样。它将提高大型数据集的性能。