MongoDB:按子文档分组并计数+添加总计数

标签 mongodb mongodb-query aggregation-framework nosql

我想要实现的目标

假设有以下子文档:

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

我要数:

  1. 根据"ip"值有多少个IP
  2. 还统计"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/

相关文章:

java - 使用 MongoDB 3.0 Java 驱动程序聚合框架时,如何在 $project 运算符中使用 $substr 表达式

mongodb - 如何在 MongoDB 中获取(或聚合)数组的不同键

MongoDB - 如何查询没有任何空格的字符串(省略带空格的字符串)和长度

mongodb - 无法使用 express.js 中的 put 请求更新数据库

mongodb - 如何计算 mongodb 中的 $lookup 字段?

arrays - MongoDB 查询子文档数组的第 n 个元素(变量索引)

node.js - 当ForeignField在数组中时查找

database - 带有 $group 和 $count 指针引用的 MongoDB 聚合管道返回错误数据

node.js - Nodejs 应用程序错误 : bind EADDRINUSE when use pm2 deploy

javascript - 仅对现有字段进行排序