【问题标题】:Mongodb aggregate (count) on multiple fields simultaneouslyMongodb同时在多个字段上聚合(计数)
【发布时间】:2014-11-08 16:43:28
【问题描述】:

我有如下文件:

{
    "_id" : "someuniqueeventid",
    "event" : "event_type_1",
    "date" : ISODate("2014-01-14T00:00:00Z"),
}

我想按“event”分组,并计算一周中每一天发生的每种事件类型的数量。基本上,我想得到类似的东西:

{
    "_id": "event_type_1",
    "1": "number of event_type_1 for Monday",
    "2": "number of event_type_1 for Tuesday",
    ...
},
{
    "_id": "event_type_2",
    ...
}

不幸的是,我被困在:

db.data.aggregate([ {$project: {date_of_week: {$dayOfWeek: "$date"}, event: "$event"}}, 
                    {$group: {_id: "$event", .... } ])

有什么想法吗?

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    聚合框架不会根据数据创建键,不应该你甚至应该这样做,因为“数据”不是键而是数据,所以你应该坚持这个模式。

    这意味着您基本上可以这样做:

    db.data.aggregate([
        { "$group": {
            "_id": {
                "event_type": "$event",
                "day": { "$dayOfWeek": "$date" }
            },
            "count": { "$sum": 1 } 
        }}
    ])
    

    这将计算每个事件在一周中每天的发生次数,尽管输出中的多个文档,但这很容易更改为每个事件的单个文档:

    db.data.aggregate([
        { "$group": {
            "_id": {
                "event_type": "$event",
                "day": { "$dayOfWeek": "$date" }
            },
            "count": { "$sum": 1 } 
        }},
        { "$group": {
            "_id": "$_id.event_type",
            "days": { "$push": { "day": "$_id.day", "count": "$count" } }
        }}
    ])
    

    这是一个数组形式,但它仍然包含你想要的结果。

    如果你真的一心想要做你的确切形式,那么你想做这样的事情:

    db.data.aggregate([
        { "$group": {
            "_id": "$event",
            "1": {
                "$sum": {
                    "$cond": [
                        { "$eq": [{ "$dayOfWeek": "$date" }, 1 ] },
                        1,
                        0
                    ]
                }
            },
            "2": {
                "$sum": {
                    "$cond": [
                        { "$eq": [{ "$dayOfWeek": "$date" }, 2 ] },
                        1,
                        0
                    ]
                }
            },
            "3": {
                "$sum": {
                    "$cond": [
                        { "$eq": [{ "$dayOfWeek": "$date" }, 3 ] },
                        1,
                        0
                    ]
                }
            },
            "4": {
                "$sum": {
                    "$cond": [
                        { "$eq": [{ "$dayOfWeek": "$date" }, 4 ] },
                        1,
                        0
                    ]
                }
            },
            "5": {
                "$sum": {
                    "$cond": [
                        { "$eq": [{ "$dayOfWeek": "$date" }, 5 ] },
                        1,
                        0
                    ]
                }
            },
            "6": {
                "$sum": {
                    "$cond": [
                        { "$eq": [{ "$dayOfWeek": "$date" }, 6 ] },
                        1,
                        0
                    ]
                }
            },
            "7": {
                "$sum": {
                    "$cond": [
                        { "$eq": [{ "$dayOfWeek": "$date" }, 7 ] },
                        1,
                        0
                    ]
                }
            }
        }}
    )
    

    但这真的很啰嗦,所以恕我直言,我会坚持第一个或第二个解决方案,因为它们更短且更易于阅读。

    【讨论】:

    • 哇!现在看起来很容易,我总是忘记我可以在 _id 中粘贴多个字段 :( 谢谢!
    • 在你的第二个例子中,$day 应该是$_id.day,不是吗?
    【解决方案2】:

    在 MongoDb 3.4.4 及更高版本中,您可以利用 $arrayToObject 运算符来获取计数。您需要运行以下聚合管道:

    db.data.aggregate([
        { 
            "$group": {
                "_id": {
                    "event": "$event",
                    "day": { "$substr": [ { "$dayOfWeek": "$date" }, 0, -1 ] }
                },
                "count": { "$sum": 1 }
            }
        },
        { 
            "$group": {
                "_id": "$_id.event",
                "counts": {
                    "$push": {
                        "k": "$_id.day",
                        "v": "$count"
                    }
                }
            }
        },
        { 
            "$project": {
                "counts": { "$arrayToObject": "$counts" }
            } 
        }    
    ])
    

    【讨论】:

    • $arrayToObject 从版本 3.4.4 开始可用。
    • @AsyaKamsky 为澄清和更新的答案干杯。
    猜你喜欢
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多