Mongodb聚合 $unwind然后计数

8
这是我的问题:在Mongo数据库中,我有一个集合,其中包含类似以下项目的内容:
{
  'id': 1,
  'steps': [
    {
      action: 'start',
      info: 'foo'
    },
    {
      action: 'stop',
      info: 'bar'
    }
  ]
}

我想获取“start”步骤的总数。我尝试使用MongoDB聚合框架:在steps.action上使用$unwind,并在steps.action上使用$match来匹配“start”。
但是,我得到了太多的数据,并达到了聚合的限制:exception: aggregation result exceeds maximum document size (16MB)。我不需要数据,我只想要计数,但我找不到如何做到这一点(使用$group没有成功)。
谢谢。
4个回答

17

如果您想要计数,可以使用此代码

db.test.count({"steps.action":"start"})

但这不会考虑步骤中是否包含多个具有“start”动作的步骤。

当您还需要计算所有具有“start”动作的步骤时,您需要展开数组,匹配步骤动作,然后分组以进行计数。

db.test.aggregate([{$unwind:"$steps"}, {$match:{"steps.action":"start"}},{ $group: { _id: null, count: { $sum: 1 } } }])

4

试一下

db.collection.aggregate([
   { $unwind : "$steps" },
   {$match:{'steps.action':'start'}},
   {$group:{_id:null,count:{$sum:1}}}
]).pretty()

0
在MongoDB的聚合框架中,管道阶段最多有100MB的大小限制,而其提供的结果是一个BSON文件或集合文档,最大大小为16MB。因此,您只能在需要的条件下进行$match,并对其进行$group,以便只输出小于16MB的所需结果。

-3

对于这个简单的查询,您可能不需要聚合。请参见下面的代码。

for (var i = 10000; i >= 0; i--) {
    var a = {
      'id': 1,
      'steps': [
        {
          action: 'start',
          info: 'foo'
        },
        {
          action: 'stop',
          info: 'bar'
        }
      ]
    }

    a.id = i;
    var rnd = Math.floor((Math.random() * 3) + 1);
    if (rnd == 1)
    {
        a.steps[0].action = 'none';
    }
    if (rnd == 2)
    {
        a.steps.push({ action: 'start', info: 'foo' })

    }
    db.obj.insert(a);
};

这段代码创建了随机数量的操作。 如果您只需要包含动作:“start”的文档数量,则使用以下查询。
db.obj.count({"steps.action":"start"})

我在运行中得到了以下计数。
> db.obj.count({"steps.action":"start"})
6756

但如果您需要文档中 {action: 'start'} 的数量,则需要聚合查询。您需要展开然后匹配。

db.obj.aggregate(
[
{ $unwind : "$steps"},
{$match: { "steps.action" : "start" }},
{
$group:
 {
   _id:  null
   ,count: { $sum: 1 }
 }
}
]
)

这将输出:

{ "_id" : null, "count" : 10054 }



if you get your exception again use **allowDiskUse : true** option. See [here][1].

db.obj.aggregate(
[
 ....
]
 ,
 { 
   allowDiskUse : true
 }

)

$match之后的$unwind不会产生正确的计数。 - Jehof
为什么?如果我先过滤还是后过滤有什么关系吗? - Atilla Ozgur
因为 $match 不会减少 steps 数组的元素,它只会找到具有 action="start" 的数组元素。steps 数组将包含与之前相同的元素。 - Jehof
1
@Jehof 你说得对。它们给出了不同的输出,我已经更新了我的答案。我需要思考/阅读一下。你能给我一个参考吗? - Atilla Ozgur

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