我希望在给出类型的集合上进行聚合。如果类型为 foo ,我想按作者字段进行分组,如果类型为栏,我想按用户<进行分组/强>
所有这些都应该在一个查询中发生。
示例数据:
{
"_id": 1,
"author": {
"someField": "abc",
},
"type": "foo"
}
{
"_id": 2,
"author": {
"someField": "abc",
},
"type": "foo"
}
{
"_id": 3,
"user": {
"someField": "abc",
},
"type": "bar"
}
如果类型为 bar ,则此用户字段仅存在。
所以基本上就是这样...试图用$or
来表达它。
function () {
var results = db.vote.aggregate( [
{ $or: [ {
{ $match : { type : "foo" } },
{ $group : { _id : "$author", sumAuthor : {$sum : 1} } } },
{ { $match : { type : "bar" } },
{ $group : { _id : "$user", sumUser : {$sum : 1} } }
} ] }
] );
return results;
}
有人有一个很好的解决方案吗?
答案 0 :(得分:2)
我认为可以通过
来完成db.c.aggregate([{
$group : {
_id : {
$cond : [{
$eq : [ "$type", "foo"]
}, "author", "user"]
},
sum : {
$sum : 1
}
}
}]);
答案 1 :(得分:0)
下面的解决方案可以稍微清理一下......
对于“bar”(注意:对于“foo”,你必须改变一点)
db.vote.aggregate(
{
$project:{
user:{ $ifNull: ["$user", "notbar"]},
type:1
}
},
{
$group:{
_id:{_id:"$user.someField"},
sumUser:{$sum:1}
}
}
)
另请注意:在最终答案中,任何非“bar”类型的内容都将具有_id = null
答案 2 :(得分:0)
这里你想要的是$cond
运算符,它是一个三元运算符,返回条件为真或假的特定值。
db.vote.aggregate([
{ "$group": {
"_id": null,
"sumUser": {
"$sum": {
"$cond": [ { "$eq": [ "$type", "user" ] }, 1, 0 ]
}
},
"sumAuhtor": {
"$sum": {
"$cond": [ { "$eq": [ "$type", "auhtor" ] }, 1, 0 ]
}
}
}}
])
这基本上测试&#34;类型&#34;当前文档,并决定是否将1
或0
传递给$sum
操作。
这也可以避免错误的分组,如果&#34;用户&#34;和&#34;作者&#34;字段包含与示例中相同的值。最终结果是一个包含两种类型计数的单个文档。