滤波部分可使用$addFields
管道兼作以在$group
_id
键和随后$match
管道中使用的字段来完成。这样的骨干是运营商,它将评估产生所需日期的要求中的条件。
单$redact
管道就足够了,但因为你还需要逻辑组过滤的文件,你还不如用$addFields
管道创建具有这样的逻辑领域。
下面的例子说明这一概念:
db.sensors.aggregate([
{
"$addFields": {
"yearMonthDay": {
"$cond": [
{ /* check if date hour is less than 8 */
"$lt": [
{ "$hour": "$date" },
8
]
},
{ /* subtract one day from a measurement at < 08:00 */
"$dateToString": {
"format": "%Y-%m-%d",
"date": {
"$subtract": [
"$date",
1000 * 60 * 60 * 24
]
}
}
},
{ /* else return actual date */
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$date"
}
}
]
},
"isNight": {
"$or": [
{ "$gte": [ { "$hour": "$date" }, 21 ] },
{ "$lt": [ { "$hour": "$date" }, 8 ] }
]
}
}
},
{ "$match": { "isNight": true } },
{
"$group": {
"_id": "$yearMonthDay",
"count": { "$sum": 1 }
}
}
])
一个更详细的方法涉及使用在适当位置的$cond
的$switch
情况下表达如下(感谢@Styvane):
db.sensors.aggregate([
{
"$addFields": {
"yearMonthDay": {
"$switch": {
"branches": [
{
"case": { "$lt": [ { "$hour": "$date" }, 8 ] },
"then": { /* subtract one day from a measurement at < 08:00 */
"$dateToString": {
"format": "%Y-%m-%d",
"date": {
"$subtract": [
"$date",
1000 * 60 * 60 * 24
]
}
}
}
},
{
"case": { "$gte": [ { "$hour": "$date" }, 8 ] },
"then": { /* return actual date */
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$date"
}
}
}
]
}
},
"isNight": {
"$or": [
{ "$gte": [ { "$hour": "$date" }, 21 ] },
{ "$lt": [ { "$hour": "$date" }, 8 ] }
]
}
}
},
{ "$match": { "isNight": true } },
{
"$group": {
"_id": "$yearMonthDay",
"count": { "$sum": 1 }
}
}
])
如何取代'$ cond'机智h'$ switch'? – styvane
真的是一回事,取决于OP想要查询的详细程度,否则我相信性能方面不会有太大影响,如果我错了,请纠正我。 – chridam
你是对的,我不想在这里迂腐,但它也使你的意图清楚,毕竟你在MongoDB 3.4中做这个:) – styvane