2017-04-26 87 views
0

使用聚合总和不同的领域我有一个test收集文档模式是这样的:MongoDB中

{ 
    "_id" : NumberLong("A unique number"), 
    "text" : { 
     "characters_map" : { 
          "a" : 4, 
          "f" : 3, 
          "b" : 6, 
          ... 
          "o" : 3 
         } 
      ... 
     } 
    ... 
} 

我要统计每个字符的总和整个收藏。我尝试使用aggregation framework,但它似乎并没有正确。

我开始时分别计算每个字符(即'a'),但没有运气。我最好的办法是:

> db.test.aggregate([ 
    { "$group" : { 
     _id : { a_count : "$text.characters_map.a" }, 
     counter : { "$sum" : "$text.characters_map.a" } 
     } 
    } 
    ]) 

a_count代表id的名称。

其结果:

{ "_id" : { "a_map" : 8 }, "counter" : 8 } 
{ "_id" : { "a_map" : 5 }, "counter" : 5 } 
{ "_id" : { "a_map" : 7 }, "counter" : 21 } 
... 

不假完全是,但不是我想要的。这些结果意味着我有1个文档,其字段为:{ "a" : 8, ... },另一个文档为:{ "a" : 5, ... },另外3个文档为:{ "a" : 7, ... }

有什么办法可以将这些字段在“a”级组合在一起吗?我的方法完全错误吗?

回答

2

你有你的结构更改为类似如下:(首选)

[{ 
    "text" : { "characters_map" : [{"k":"a", "v":4}, {"k":"b", "v":8}, {"k":"c", "v":5}, {"k":"d", "v":4 }] } 
}] 

您可以使用您的聚集在您的文章尝试的方式。

db.test.aggregate([ 
{$unwind:"$text.characters_map"}, 
{$group:{_id:"$text.characters_map.k", counter:{$sum:"$text.characters_map.v"}}} 
]) 

这是解决方案,如果你不能改变你的结构。

您可以使用3.4.4版本并使用$objectToArray & $arrayToObject在动态键和标签值对之间切换。

阶段1:将动态characters_map密钥转换为标签值对。

第2阶段& 3:$unwind & $group上的字符和总数。

阶段4 & 5:将来自最后一组的输出分组回密钥值对的数组,然后输入$arrayToObject将密钥值对转换为动态密钥。

db.test.aggregate([ 
{$addFields: {"text.characters_map": {$objectToArray: "$text.characters_map"}}}, 
{$unwind:"$text.characters_map"}, 
{$group:{_id:"$text.characters_map.k", counter:{$sum:"$text.characters_map.v"}}}, 
{$group:{_id:null, arraykeyval:{$push:{k:"$_id", v:"$counter"}}}}, 
{$project:{result: {$arrayToObject:"$arraykeyval"}}} 
]) 
+0

工程就像一个魅力!也非常感谢架构重构建议,我没有想到它!现在它是有道理的... –