同时对多个字段进行Mongodb聚合(计数)

同时对多个字段进行Mongodb聚合(计数),mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有这样的文件: { "_id" : "someuniqueeventid", "event" : "event_type_1", "date" : ISODate("2014-01-14T00:00:00Z"), } db.data.aggregate([ { "$group": { "_id": "$event", "1": { "$sum": { "$cond": [

我有这样的文件:

{
    "_id" : "someuniqueeventid",
    "event" : "event_type_1",
    "date" : ISODate("2014-01-14T00:00:00Z"),
}
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": "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", .... } ])

有什么想法吗?

聚合框架不会基于数据创建键,您甚至不应该这样做,因为“数据”不是键,而是实际数据,所以您应该坚持这种模式

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

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" } }
    }}
])
这是一个数组形式,但它仍然保存您想要的结果

如果你真的致力于做你的精确形式,那么你想做如下事情:

{
    "_id" : "someuniqueeventid",
    "event" : "event_type_1",
    "date" : ISODate("2014-01-14T00:00:00Z"),
}
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
                ]
            }
        }
    }}
)

但是这真的很冗长,所以我会坚持使用第一个或第二个解决方案,因为它们更短,更容易阅读。

对于MongoDb 3.4.4和更新版本,您可以利用操作符来获取计数。您需要运行以下聚合管道:

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" }
        } 
    }    
])

啊!现在似乎很容易,我总是忘记我可以在_id中粘贴多个字段:(谢谢!在第二个示例中,
$day
应该是
$_id.day
,没有?$arrayToObject从3.4.4版开始提供。@AsyaKamsky为澄清而欢呼,更新了答案。