我有一个结构,用户创建的对象可以以特定的Document键结尾。我知道关键是什么,但是我不知道潜在价值的结构是什么。出于我的问题的目的,我们假设它是一个数组,单个值或一个字典。
为了获得更多乐趣,我还尝试解决嵌套字典的问题。
我想做的是在所有具有此键的对象上运行聚合,并汇总结构的终端节点的值。例如,如果我有以下内容:
ObjectA.foo = {"a": 2, "b": 4}
ObjectB.foo = {"a": 8, "b": 16}
ObjectC.bar = {"nested": {"d": 20}}
ObjectD.bar = {"nested": {"d": 30}}
我想最终得到一个输出值
foo.a = 10
foo.b = 20
bar.nested.d = 50
我最初的想法是尝试弄清楚如何使Mongo扁平化层次结构的键。如果我可以将源数据从对象分解为一系列键值(其中键代表值的整个路径),则可以轻松地对此进行汇总。但是,我不确定该怎么做。
理想情况下,我会有类似$ unwindKeys之类的东西,但是可惜没有这样的运算符。有一个$ objectToArray,我想我可以然后$ unwind,但是那时候我已经开始迷失在堆叠这些运算符。尽管我认为单深度解决方案将是一个好的开始,但它也不能解决任意深度的问题。
有什么想法吗?
编辑:因此,我已经使用$objectToArray解决了单深度问题。看哪:
db.mytable.aggregate(
[
{
'$project': {
'_id': false,
'value': {
'$objectToArray': '$data.input_field_with_dict'
}
}
},
{
'$unwind': '$value'
},
{
'$group': {
'_id': '$value.k',
'sum': {
'$sum': '$value.v'
}
}
}
]
)
这将为您提供所选文档中的键值对,然后可以对其进行迭代。因此,在上述示例涉及ObjectA和ObjectB的情况下,上述查询的结果将是:
{"_id": "a", "sum": 10}
{"_id": "b", "sum": 20}
我仍然不知道如何递归遍历该结构。 $ objectToArray解决方案可以在具有未知键的单个已知级别上正常工作,但是如果您同时拥有未知键和深度,则我没有解决方案。
搜索继续:如何递归求和或至少投影具有嵌套结构的字段并保留其键序列?换句话说,如何展平未知深度的结构?如果我可以展平,那时候我可以很容易地聚集在键上。
答案 0 :(得分:0)
如果您的收藏是这样的
/* 1 */
{
"a" : 2,
"b" : 4
}
/* 2 */
{
"a" : 8,
"b" : 16
}
/* 3 */
{
"nested" : {
"d" : 20
}
}
/* 4 */
{
"nested" : {
"d" : 30
}
}
下面的查询将为您提供所需的结果。
db.sof.aggregate([
{'$group': {
'_id': null,
'a': {$sum: '$a'},
'b': {$sum: '$b'},
'd': {$sum: '$nested.d'}
}}
])