【问题标题】:$sum from documents and subdocuments group by "$author" (MongoDB)$sum 来自“$author”(MongoDB)的文档和子文档组
【发布时间】:2015-03-09 00:51:52
【问题描述】:

这是我的收藏:

{
        "_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"
                }
        ]
}

我想要每个authorvotescomments.votes$sum

预期输出(sort $votes: -1):

"Mirek" total votes: 31 + 75 + 29 = 135

"Jesse" total votes: 131 + 17 = 148

"Leszke total votes: 13

【问题讨论】:

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


    【解决方案1】:

    不是立即可见,但可能。您需要在这里做的是将您的顶级文档与 cmets 数组结合起来,而不是复制它。这是一种方法,首先将内容作为两个数组加入单个数组,然后$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,它本质上链接到相同的底层代码。这里有两种情况使用它来为数组提供模板元素,或者作为引入数组展开以在两个操作之间提供“二元选择”。

    【讨论】:

      【解决方案2】:

      您可以将结果汇总如下:

      • Unwind cmets 数组。
      • Group记录一起先计算总票数 每位作者在他的 cmets 中收到。同时保留原件 机智的帖子。
      • Unwind 原始帖子数组。
      • 现在project 每个作者的总和。
      • Sort 作者姓名和投票。
      • 从每个组中选择第一条记录以消除重复。

      代码:

      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 }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-26
        • 2023-03-28
        • 2014-09-26
        相关资源
        最近更新 更多