javascript - 文档和子文档的 $sum 按 "$author"(MongoDB)

标签 javascript node.js mongodb mongodb-query aggregation-framework

这是我的收藏:

{
        "_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$sum votescomments.votes

预期输出(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 } }
])

那些使用诸如 $setUnion 之类的运算符甚至 $map从 MongoDB 2.6 开始引入。这使得它更简单,但它仍然可以在缺少这些运算符的早期版本中完成,遵循大致相同的原则:

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它本质上链接到相同的底层代码。它在此处的两种情况下被用于为数组提供模板元素,或者引入要展开的数组以便在两个操作之间提供“二元选择”。

关于javascript - 文档和子文档的 $sum 按 "$author"(MongoDB),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27881942/

相关文章:

javascript - 从 JS 脚本释放浏览器内存

mysql - 获取 DatabaseError [SequelizeDatabaseError],整数值不正确

node.js - 模块化编程和 Node

Spring 数据 mongodb @DBRef 列表

database - 如何在 IBM Cloud MongoDB 数据库上设置自动缩放?

mongodb - mongodb 聚合是否应该与性能关键的 Http 请求一起使用

javascript - 任意数量对象的交集

javascript - 在javascript中将矩阵旋转45度

javascript - 如何将 vis.js 中的箭头更改为鸡脚或基数

node.js - 无法在 electron-forge 中使用 electron-packager 构建