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

3

我想要实现的目标

假设有以下子文档:

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

为了实现我上面所说的,但是我卡在那里,一直无法做到。
1个回答

1

在同一个聚合管道中不可能实现,因为原则上管道会在文档通过时处理文档,即管道阶段不需要为每个输入文档生成一个输出文档;例如,某些阶段可能会生成新文档或过滤文档。在上述情况下,添加另一个$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
  }
]

1
谢谢你的回复,它帮助我意识到并以不同的方式找到解决方案! - charliebrownie
@charliebrownie 不用担心,很高兴能帮到你 :) - chridam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接