【问题标题】:Mongodb: aggregate array of integers for each array position without map/reduceMongodb:每个数组位置的整数数组聚合,没有map/reduce
【发布时间】:2017-06-26 16:03:52
【问题描述】:

我是 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

【问题讨论】:

  • 为什么工作解决方案不够好?

标签: mongodb aggregation-framework


【解决方案1】:

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

在此示例中,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 操作,成本很高,因此我建议您针对您的数据集衡量这两种解决方案的性能,然后选择最适合您的应用程序的一种。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      • 2015-08-31
      • 1970-01-01
      • 2014-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多