Mongodb:没有map/reduce的每个数组位置的整数聚合数组

Mongodb: aggregate array of integers for each array position without map/reduce

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

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 来做到这一点?下面 link 显示了一个 map/reduce 解决方案,但我正在寻找一种替代方法来实现相同的目标。谢谢!

Mongodb: aggregate array of integers for each array position

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

在此示例中,values 数组元素 无法通过路径 values.0values.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 操作,成本很高,我建议您根据您的数据集衡量这两种解决方案的性能,然后选择最适合您的应用程序的解决方案。

感谢您的回复。更改架构可能是解决此问题的最佳方法。正如您所指出的, $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
}