Mongodb 对集合中文档的相同命名字段的所有值求和

Mongodb 对集合中文档的相同命名字段的所有值求和,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有一个包含以下文档的数据库: { name: "John", a: 20, b: 30, c: 40, d: 50 }, { name: "Rich", a: 20, b: 30, c: 40, d: 50 }, { name: "Anne", a: 20, b: 30, c: 40, d: 50 }, { name: "Sam", a: 20, b: 30, c: 40, d: 50 }, 我想计算在这些领域花费的总小时数。我通过以下方式实现了这一

我有一个包含以下文档的数据库:

{ name: "John", a: 20, b: 30, c: 40, d: 50  },     
{ name: "Rich", a: 20, b: 30, c: 40, d: 50  },      
{ name: "Anne", a: 20, b: 30, c: 40, d: 50  },      
{ name: "Sam", a: 20, b: 30, c: 40, d: 50  },
我想计算在这些领域花费的总小时数。我通过以下方式实现了这一目标:

db.hours.aggregate([{$group: {_id: null, totalA: {$sum: "$a"}, totalB: {$sum: "$b"}, totalC: {$sum: "$c"}, totalD: {$sum: "$d"}}}])
{ "_id" : null, "totalA" : 80, "totalB" : 120, "totalC" : 160, "totalD" : 200 }
因为在某个时刻,每个文档中都会有几十个字段,有没有更简单的方法动态生成总字段?如中所示:检查文档中的所有字段,如果它们存在于集合中的其他文档中,则将它们全部相加。如果它们不存在于其他文档中,只需将该字段值显示为总计。例如,如果我有:

{ name: "John", a: 20, b: 30, e: 40, f: 50  },     
{ name: "Rich", a: 20, b: 30, c: 40, d: 50  },      
{ name: "Anne", a: 20, b: 30, g: 40, h: 50  },      
{ name: "Sam", a: 20, b: 30, c: 40, d: 50  },
应导致:

{"a" : 80, "b" : 120, "c" : 80, "d" : 100, "e" : 40, "f" : 50, "g" : 40, "h": 50 }
有什么建议吗?无需手动写入上述聚合示例中的所有总和

谢谢

您可以利用和运算符动态读取对象键。要删除_id和name字段,您可以通过

您可以利用和运算符动态读取对象键。要删除_id和name字段,您可以通过


有没有办法对结果进行排序?在Mongo游乐场中,我得到了期望的结果[{a:80,b:120,c:80,d:100,e:40,f:50,g:40,h:50}],但在我的控制台中,它显示为未排序的{h:50,c:80,g:40,f:50,e:40,d:100,b:120,a:80}。尝试添加一个{$sort:{{u id:1}}或类似的东西,但没有效果,因为不知道$replaceRoot阶段之后的变量名称,而该阶段感兴趣的是按字母顺序或按总数排序amount@jio我知道它看起来很糟糕,但是你不应该依赖于BSON键的顺序-它意味着不确定性:,也许你可以试着把你的$sort放在$group的两个阶段之间,比如:有没有办法对结果进行排序?在Mongo游乐场中,我得到了期望的结果[{a:80,b:120,c:80,d:100,e:40,f:50,g:40,h:50}],但在我的控制台中,它显示为未排序的{h:50,c:80,g:40,f:50,e:40,d:100,b:120,a:80}。尝试添加一个{$sort:{{u id:1}}或类似的东西,但没有效果,因为不知道$replaceRoot阶段之后的变量名称,而该阶段感兴趣的是按字母顺序或按总数排序amount@jio我知道它看起来很糟糕,但是你不应该依赖于BSON键的顺序-它意味着不确定性:,也许您可以尝试将$sort放在$group阶段之间,如:
db.collection.aggregate([
    {
        $project: {
            _id: 0,
            fields: {
                $filter: {
                    input: { $objectToArray: "$$ROOT" },
                    cond: { $eq: [ { $type: "$$this.v" }, "double" ] }
                }
            }
        }
    },
    {
        $unwind: "$fields"
    },
    {
        $group: {
            _id: "$fields.k",
            total: { $sum: "$fields.v" }
        }
    },
    {
        $group: {
            _id: null,
            aggregates: { $push: { k: "$_id", v: "$total" } }
        }
    },
    {
        $replaceRoot: {
            newRoot: { $arrayToObject: "$aggregates" }
        }
    }
])