Mongodb 计算mongo聚合(pymongo)中的记录类型

Mongodb 计算mongo聚合(pymongo)中的记录类型,mongodb,pymongo,mongodb-query,aggregation-framework,Mongodb,Pymongo,Mongodb Query,Aggregation Framework,我正在使用pymongo进行以下聚合(users以前定义为我要查询的用户列表): 这给了我以下结果: {u'ok': 1.0, u'result': [{u'_id': u'user22', u'badges': [u'gold', u'silver', u'silver']}, {u'_id': u'user2', u'badges': [u'gold', u'gold']}, {u'

我正在使用pymongo进行以下聚合(
users
以前定义为我要查询的用户列表):

这给了我以下结果:

{u'ok': 1.0,
 u'result': [{u'_id': u'user22',
              u'badges': [u'gold', u'silver', u'silver']},
             {u'_id': u'user2',
              u'badges': [u'gold', u'gold']},
             {u'_id': u'user15',
              u'badges': [u'gold', u'bronze', u'bronze']},
             {u'_id': u'user11',
              u'badges': [u'gold']},
             {u'_id': u'user3',
              u'badges': [u'silver', u'bronze']},
             {u'_id': u'user18',
              u'badges': [u'bronze']}
            ]
}
这没关系,但我真正想得到的是每种奖牌类型的计数(类型=金/银/铜)。我可以在Python的后处理中轻松做到这一点,但我觉得我应该能够在相同的管道中做到这一点,我想学习“如何更好地使用mongo”:

所以说得清楚一点,我真正想要的是(我手工生成了这个理想的输出,因此可能与上面的数据不一致或语法错误,但我认为这能说明问题):

我的数据结构要求并不严格。我也很乐意使用金/银/铜作为键,并避免使用嵌套的dict:

{u'_id': u'user22',
 u'gold': 1, u'silver': 2},
{u'_id': u'user2',
 u'gold': 2},
...
我试着用
$sum
操作符做了很多事情,但是运气不好。当我尝试动态生成字段名时,我得到:

失败:异常:组聚合字段名“$badge”不能是操作员名

有什么想法吗?提前谢谢


(还有,半相关的…我对map reduce不太了解。也许这是一个候选。我开始使用聚合,到目前为止它们对我很有效。我可能也应该了解map reduce)

除了将徽章推送到数组之外,你还可以做些什么,取决于徽章类型。这通常通过测试操作员内部的条件来完成,以确定“总和”的贡献量:

collection.aggregate([
{“$match”:{“user”:{“$in”:users}}},
{“$组”:{
“_id”:“$user”,
“黄金”:{
“$sum”:{
“$cond”:[
{“$eq”:[“$badge”,“gold”]},
1.
0
]
}
},
“银”:{
“$sum”:{
“$cond”:[
{“$eq”:[“$badge”,“silver”]},
1.
0
]
}
},
“青铜”:{
“$sum”:{
“$cond”:[
{“$eq”:[“$badge”,“Brown”]},
1.
0
]
}
}
}}
])
这将正确地将每个类型相加,当然每个用户都会有一个“金/银/铜”计数,不管它是否大于0。您不能在聚合框架中“动态”创建字段


如果您真的需要“动态”字段,那么您唯一的选择就是mapReduce,但这当然不会像聚合框架那样高效。条件和确实为您提供了最佳选择。

感谢@neil lunn的更新。现在,我看到了您如何在其中添加
$cond
,看起来我缺少了第一个参数周围的大括号-我仍然习惯于所有的标点符号。
{u'ok': 1.0,
 u'result': [{u'_id': u'user22',
              u'badges': {u'gold': 1, u'silver': 2}},
             {u'_id': u'user2',
              u'badges': {u'gold': 2}},
             {u'_id': u'user15',
              u'badges': {u'gold': 1, u'bronze': 2}},
             {u'_id': u'user11',
              u'badges': {u'gold': 1}},
             {u'_id': u'user3',
              u'badges': {u'silver': 1, u'bronze': 1}},
             {u'_id': u'user18',
              u'badges': {u'bronze': 1}}
            ]
}
{u'_id': u'user22',
 u'gold': 1, u'silver': 2},
{u'_id': u'user2',
 u'gold': 2},
...