【问题标题】:Group MongoDB data by date of night按日期对 MongoDB 数据进行分组
【发布时间】:2017-08-04 07:20:27
【问题描述】:

MongoDB 3.4 集合将包含时间戳的传感器信息存储为 ISODate 字段。

无论是在day还是night,都需要对传感器信息进行不同的处理,其中night表示>= 20.00(晚上8点)和 $hour 来检查测量是day 还是night

根据要求,所有夜间测量都属于夜晚开始的日期,即 21.00 的测量日期适合,而需要从 03.00 的测量中减去一天。

我想对所有 night 措施进行聚合($match 步骤过滤掉全天措施,这不是问题)并按当晚日期分组。你知道我该怎么做吗?我考虑过使用$project 步骤并获取时间信息,但不确定如何生成可用于组操作的有效_id

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    过滤部分可以使用 $addFields 管道完成,该管道还用于创建要在 $group _id 键和随后的 $match 管道。这样的主干是 $cond 运算符,它将评估需求中的条件以产生所需的日期。

    单个 $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 }
            }
        }
    ])
    

    更详细的方法是使用 $switch 案例表达式代替 $cond,如下所示(感谢@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 }
            }
        }
    ])
    

    【讨论】:

    • $switch替换$cond怎么样?
    • 同样的事情,取决于 OP 希望查询的详细程度,否则我相信性能方面不会有太大影响,如果我错了,请纠正我。
    • 你说得对,我不是想在这里学究气,但它也让你的意图很清楚,毕竟你在 MongoDB 3.4 中这样做:)
    • 干杯@Styvane :) 永远感谢您的意见
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 1970-01-01
    • 2023-02-07
    • 2019-03-05
    • 2016-10-08
    • 1970-01-01
    • 2018-03-04
    相关资源
    最近更新 更多