3

我有一个 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 操作作为 telemetryDate 存储到我可以与 $in 运算符进行比较的 day 变量中。

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

4

2 回答 2

4

您应该在$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> ]

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

于 2013-06-21T17:51:59.820 回答
3

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

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

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

上面说:“通过这三个字段,还计算一个新字段alarmWeekdays,如下所示:......”

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

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`
于 2013-06-22T03:37:29.313 回答