Mongodb:每个数组位置的聚合数组,不带map / reduce

时间:2015-02-09 07:31:34

标签: mongodb aggregation-framework

我是MongoDB的新手。我想知道是否可以聚合数组中的每个“列”。假设我们有以下文件:

db.test.insert([{"player": "A", "year": 2010, "value": [1, 1 ]},
                {"player": "A", "year": 2011, "value": [2, 1 ]},
                {"player": "A", "year": 2012, "value": [2, 1 ]},
                {"player": "B", "year": 2010, "value": [1, 2 ]}])

预期结果应该是:

      [
        {
        "player": "A",
        "sum_result": [
            5,
            3
        ]
        },
        {
        "player": "B",
        "sum_result": [
            1,
            2
        ]
        }
    ]

是否可以在不使用Map / Reduce的情况下执行此操作?下面的链接显示了map / reduce解决方案,但我正在寻找另一种方法来实现相同的目标。谢谢!

Mongodb: aggregate array of integers for each array position

2 个答案:

答案 0 :(得分:0)

只有当文件中的元素可以通过路径名到达时,大多数问题才能在聚合中解决。

在此示例中,路径valuesvalues.0无法访问values.1数组元素

因此,要解决此类问题,您需要选择map-reduce,这样可以提供更大的灵活性。

不幸的是,除非您更改架构,否则在这种情况下无法使用聚合获得所需的输出。其中一个例子是制作values字段 - 一组文档。在这里,值数组中的所有元素都可以通过路径名来访问,例如values.c1(表示列1中的值)

db.t.insert([ 
{"player":"A","year":2010,"value":[ {"c1":1}, {"c2":1}]},
{"player":"A","year":2011,"value":[ {"c1":2}, {"c2":1}]},
{"player":"A","year":2012,"value":[ {"c1":2}, {"c2":1}]},
{"player":"B","year":2010,"value":[ {"c1":1}, {"c2":2}]}
])

然后您可以将其汇总如下:

db.t.aggregate([
{$unwind:"$value"},
{$group:{"_id":"$player",
         "c1":{$sum:"$value.c1"},
         "c2":{$sum:"$value.c2"}}},
{$group:{"_id":"$_id",
         "c1":{$push:{"c1":"$c1"}},
         "c2":{$push:{"c2":"$c2"}}}},
{$project:{"value":{$setUnion:["$c1","$c2"]}}}
])

O / P:

{ "_id" : "A", "value" : [ { "c1" : 5 }, { "c2" : 3 } ] }
{ "_id" : "B", "value" : [ { "c2" : 2 }, { "c1" : 1 } ] }

由于解决方案涉及$unwind操作,这是昂贵的,我建议您根据数据集衡量两种解决方案的性能,并选择最适合您应用的解决方案。

答案 1 :(得分:0)

感谢您的回复。更改架构可能是解决此问题的最佳方法。正如您所指出的, $ unwind 操作可能代价高昂。我最终决定使用以下解决方案。

修订文件:

db.test.insert([{"player": "A", "year": 2010, "values": {"v1":1, "v2":1 }},
                {"player": "A", "year": 2011, "values": {"v1":2, "v2":1 }},
                {"player": "A", "year": 2012, "values": {"v1":2, "v2":1 }},
                {"player": "B", "year": 2010, "values": {"v1":1, "v2":2 }}])

查询声明:

db.test.aggregate([
    {$group:{"_id":"$player", 
             "v1":{$sum:"$values.v1"},
             "v2":{$sum:"$values.v2"}}},
    {$project:{"values":{"v1":"$v1","v2":"$v2"}}}
]) 

输出:

{
    "result": [{
        "_id": "B",
        "values": {
            "v1": 1,
            "v2": 2
        }
    }, {
        "_id": "A",
        "values": {
            "v1": 5,
            "v2": 3
        }
    }],
    "ok": 1
}