我想要实现的目标
假设有以下子文档:
{
"id":1,
"url":"mysite.com",
"views":
[
{"ip":"1.1.1.1","date":"01-01-2015"},
{"ip":"2.2.2.2","date":"01-01-2015"},
{"ip":"1.1.1.1","date":"01-01-2015"},
{"ip":"1.1.1.1","date":"01-01-2015"}
]
}
我要数:
- 根据
"ip"
值有多少个IP - 和还统计
"views"
中的子文档总数
如果可能在同一个查询中,实现以下结果:
[
{
"_id":"2.2.2.2",
"count":1
},
{
"_id":"1.1.1.1",
"count":3
},
{
"_id":"total",
"count":4
}
]
到目前为止我取得了什么
使用 MongoDB 聚合框架,我已经通过以下方式实现了第 1. 点:
db.collection.aggregate([
{
"$unwind": "$views"
},
{
"$group": {
"_id": "$views.ip",
"count": {
"$sum": 1
}
}
}
])
返回:
[
{
"_id":"2.2.2.2",
"count":1
},
{
"_id":"1.1.1.1",
"count":3
}
]
我希望返回数组中的额外文档,即:
{
"_id":"total",
"count":4
}
为了实现我在上面展示的内容,但我被困在那里并且无法做到这一点。
最佳答案
在同一个聚合管道中是不可能的,因为原则上管道在文档通过它时处理文档,即管道阶段不需要为每个输入文档生成一个输出文档;例如,某些阶段可能会生成新文档或过滤掉文档。在上面的场景中,添加另一个 $group
获得分组 IP 计数 + 总计数的步骤会产生与您所追求的结果不同的结果,即
db.collection.aggregate([
{
"$unwind": "$views"
},
{
"$group": {
"_id": "$views.ip",
"count": {
"$sum": 1
}
}
},
{
"$group": {
"_id": null,
"total": {
"$sum": "$count"
}
}
}
])
您只会获得自 $group
以来的总计数 使用所有输入文档(具有分组 IP 计数的文档)并为每个不同的组输出一个文档。这个额外的分组步骤将对来自上一个流的所有文档进行分组。
但是,您可以获得总计数,但作为最终结果中每个分组文档中的额外字段。以下示例使用初始 $project
管道阶段通过 $size
获取总数 运算符完成此操作:
db.collection.aggregate([
{
"$project": {
"views": 1,
"views_size": { "$size": "$views" }
}
}
{
"$unwind": "$views"
},
{
"$group": {
"_id": "$views.ip",
"count": {
"$sum": 1
},
"total": { "$first": "$views_size" }
}
}
])
示例输出
[
{
"_id": "2.2.2.2",
"count": 1,
"total": 4
},
{
"_id": "1.1.1.1",
"count": 3,
"total": 4
}
]
关于MongoDB:按子文档分组并计数+添加总计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35178741/