按“$author”分组的文档和子文档的 $sum (MongoDB)
$sum from documents and subdocuments group by "$author" (MongoDB)
这是我的collection:
{
"_id" : 10926400,
"votes": 131,
"author": "Jesse",
"comments" : [
{
"id" : 1,
"votes": 31,
"author": "Mirek"
},
{
"id": 2,
"votes": 13,
"author": "Leszke"
}
]
},
{
"_id" : 10926401,
"votes": 75,
"author": "Mirek",
"comments" : [
{
"id" : 1,
"votes": 17,
"author": "Jesse"
},
{
"id": 2,
"votes": 29,
"author": "Mirek"
}
]
}
我想要每个 author
的 votes
和 comments.votes
的 $sum
值
预期输出(sort $votes: -1
):
"Mirek" total votes: 31 + 75 + 29 = 135
"Jesse" total votes: 131 + 17 = 148
"Leszke total votes: 13
不是立即可见但可能。您需要在这里做的是将您的顶级文档与评论数组结合起来,而不是复制它。这是一种方法,首先将内容作为两个数组连接到一个单一数组中,然后 $unwind
对内容进行分组:
db.collection.aggregate([
{ "$group": {
"_id": "$_id",
"author": {
"$addToSet": {
"id": "$_id",
"author": "$author",
"votes": "$votes"
}
},
"comments": { "$first": "$comments" }
}},
{ "$project": {
"combined": { "$setUnion": [ "$author", "$comments" ] }
}},
{ "$unwind": "$combined" },
{ "$group": {
"_id": "$combined.author",
"votes": { "$sum": "$combined.votes" }
}},
{ "$sort": { "votes": -1 } }
])
给出输出:
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
{ "_id" : "Leszke", "votes" : 13 }
即使跳过第一个 $group
阶段并以不同的方式制作组合数组:
db.collection.aggregate([
{ "$project": {
"combined": {
"$setUnion": [
{ "$map": {
"input": { "$literal": ["A"] },
"as": "el",
"in": {
"author": "$author",
"votes": "$votes"
}
}},
"$comments"
]
}
}},
{ "$unwind": "$combined" },
{ "$group": {
"_id": "$combined.author",
"votes": { "$sum": "$combined.votes" }
}},
{ "$sort": { "votes": -1 } }
])
那些使用从 MongoDB 2.6 开始引入的运算符,例如 $setUnion
and even $map
。这使它更简单,但它仍然可以在缺少这些运算符的早期版本中完成,遵循大致相同的原则:
db.collection.aggregate([
{ "$project": {
"author": 1,
"votes": 1,
"comments": 1,
"type": { "$const": ["A","B"] }
}},
{ "$unwind": "$type" },
{ "$unwind": "$comments" },
{ "$group": {
"_id": {
"$cond": [
{ "$eq": [ "$type", "A" ] },
{
"id": "$_id",
"author": "$author",
"votes": "$votes"
},
"$comments"
]
}
}},
{ "$group": {
"_id": "$_id.author",
"votes": { "$sum": "$_id.votes" }
}},
{ "$sort": { "votes": -1 } }
])
$const
没有记录,但存在于存在聚合框架的所有 MongoDB 版本中(自 2.2 起)。 MongoDB 2.6 引入了 $literal
,它本质上链接到相同的底层代码。它在此处的两种情况下用于为数组提供模板元素,或者引入要展开的数组以便在两个操作之间提供 "binary choice"。
您可以汇总如下结果:
Unwind
评论数组。
Group
把记录放在一起先计算票数总和
每个作者在他的评论中收到。同时保持原来的
post完好无损。
Unwind
由原post数组
- 现在
project
每个作者的总和。
Sort
作者姓名和投票。
- Select 每组中的第一条记录以消除重复项。
代码:
db.collection.aggregate([
{$unwind:"$comments"},
{$group:{"_id":null,
"comments":{$push:"$comments"},
"post":{$addToSet:{"author":"$author",
"votes":"$votes"}}}},
{$unwind:"$comments"},
{$group:{"_id":"$comments.author",
"votes":{$sum:"$comments.votes"},
"post":{$first:"$post"}}},
{$unwind:"$post"},
{$project:{"_id":1,
"votes":{$cond:[{$eq:["$_id","$post.author"]},
{$add:["$votes","$post.votes"]},
"$votes"]}}},
{$sort:{"_id":-1,"votes":-1}},
{$group:{"_id":"$_id","votes":{$first:"$votes"}}}
])
样本o/p:
{ "_id" : "Leszke", "votes" : 13 }
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
这是我的collection:
{
"_id" : 10926400,
"votes": 131,
"author": "Jesse",
"comments" : [
{
"id" : 1,
"votes": 31,
"author": "Mirek"
},
{
"id": 2,
"votes": 13,
"author": "Leszke"
}
]
},
{
"_id" : 10926401,
"votes": 75,
"author": "Mirek",
"comments" : [
{
"id" : 1,
"votes": 17,
"author": "Jesse"
},
{
"id": 2,
"votes": 29,
"author": "Mirek"
}
]
}
我想要每个 author
votes
和 comments.votes
的 $sum
值
预期输出(sort $votes: -1
):
"Mirek" total votes: 31 + 75 + 29 = 135
"Jesse" total votes: 131 + 17 = 148
"Leszke total votes: 13
不是立即可见但可能。您需要在这里做的是将您的顶级文档与评论数组结合起来,而不是复制它。这是一种方法,首先将内容作为两个数组连接到一个单一数组中,然后 $unwind
对内容进行分组:
db.collection.aggregate([
{ "$group": {
"_id": "$_id",
"author": {
"$addToSet": {
"id": "$_id",
"author": "$author",
"votes": "$votes"
}
},
"comments": { "$first": "$comments" }
}},
{ "$project": {
"combined": { "$setUnion": [ "$author", "$comments" ] }
}},
{ "$unwind": "$combined" },
{ "$group": {
"_id": "$combined.author",
"votes": { "$sum": "$combined.votes" }
}},
{ "$sort": { "votes": -1 } }
])
给出输出:
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
{ "_id" : "Leszke", "votes" : 13 }
即使跳过第一个 $group
阶段并以不同的方式制作组合数组:
db.collection.aggregate([
{ "$project": {
"combined": {
"$setUnion": [
{ "$map": {
"input": { "$literal": ["A"] },
"as": "el",
"in": {
"author": "$author",
"votes": "$votes"
}
}},
"$comments"
]
}
}},
{ "$unwind": "$combined" },
{ "$group": {
"_id": "$combined.author",
"votes": { "$sum": "$combined.votes" }
}},
{ "$sort": { "votes": -1 } }
])
那些使用从 MongoDB 2.6 开始引入的运算符,例如 $setUnion
and even $map
。这使它更简单,但它仍然可以在缺少这些运算符的早期版本中完成,遵循大致相同的原则:
db.collection.aggregate([
{ "$project": {
"author": 1,
"votes": 1,
"comments": 1,
"type": { "$const": ["A","B"] }
}},
{ "$unwind": "$type" },
{ "$unwind": "$comments" },
{ "$group": {
"_id": {
"$cond": [
{ "$eq": [ "$type", "A" ] },
{
"id": "$_id",
"author": "$author",
"votes": "$votes"
},
"$comments"
]
}
}},
{ "$group": {
"_id": "$_id.author",
"votes": { "$sum": "$_id.votes" }
}},
{ "$sort": { "votes": -1 } }
])
$const
没有记录,但存在于存在聚合框架的所有 MongoDB 版本中(自 2.2 起)。 MongoDB 2.6 引入了 $literal
,它本质上链接到相同的底层代码。它在此处的两种情况下用于为数组提供模板元素,或者引入要展开的数组以便在两个操作之间提供 "binary choice"。
您可以汇总如下结果:
Unwind
评论数组。Group
把记录放在一起先计算票数总和 每个作者在他的评论中收到。同时保持原来的 post完好无损。Unwind
由原post数组- 现在
project
每个作者的总和。 Sort
作者姓名和投票。- Select 每组中的第一条记录以消除重复项。
代码:
db.collection.aggregate([
{$unwind:"$comments"},
{$group:{"_id":null,
"comments":{$push:"$comments"},
"post":{$addToSet:{"author":"$author",
"votes":"$votes"}}}},
{$unwind:"$comments"},
{$group:{"_id":"$comments.author",
"votes":{$sum:"$comments.votes"},
"post":{$first:"$post"}}},
{$unwind:"$post"},
{$project:{"_id":1,
"votes":{$cond:[{$eq:["$_id","$post.author"]},
{$add:["$votes","$post.votes"]},
"$votes"]}}},
{$sort:{"_id":-1,"votes":-1}},
{$group:{"_id":"$_id","votes":{$first:"$votes"}}}
])
样本o/p:
{ "_id" : "Leszke", "votes" : 13 }
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }