使用 mongo 聚合成对对文档进行分组



我有一个项目集合,

[ a, b, c, d ]

我想将它们成对分组,例如,

[ [ a, b ], [ b, c ], [ c, d ] ]

这将用于计算原始集合中每个项目之间的差异,但该部分使用几种技术来解决,例如本问题中的技术。

我知道这可以通过mapreduce来实现,但是我想知道聚合是否可以。

编辑:这是一个例子,

的集合;每个项都是一个实际文档。

[
    { val: 1 },
    { val: 3 },
    { val: 6 },
    { val: 10 },
]

分组版本:

[
    [ { val: 1 }, { val: 3 } ], 
    [ { val: 3 }, { val: 6 } ],
    [ { val: 6 }, { val: 10 } ]
]

生成的集合(或聚合结果):

[
    { diff: 2 },
    { diff: 3 },
    { diff: 4 }
]

这是聚合框架无法做到的,目前唯一可用于此类操作的MongoDB方法是mapReduce。

原因是聚合框架无法引用管道中除当前文档之外的任何其他文档。这实际上也适用于"分组"管道阶段,因为即使事情被分组到"键"上,您也无法真正按照您想要的方式处理单个文档。

另一方面,MapReduce有一个功能,允许你在这里做你想做的事,它甚至与聚合没有"直接"关系。事实上,它是在所有阶段拥有"全局范围的变量"的能力。拥有一个"变量"来基本上"存储最后一个文档"是实现结果所需的全部。

所以这是非常简单的代码,实际上不需要"缩减":

db.collection.mapReduce(
    function () {
      if (lastVal != null)
        emit( this._id, this.val - lastVal );
      lastVal = this.val;
    },
    function() {}, // mapper is not called
    {
        "scope": { "lastVal": null },
        "out": { "inline": 1 }
    }
)

这给你一个结果很像这样:

{
    "results" : [
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d662"),
                    "value" : 2
            },
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d663"),
                    "value" : 3
            },
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d664"),
                    "value" : 4
            }
    ],
    "timeMillis" : 3,
    "counts" : {
            "input" : 4,
            "emit" : 3,
            "reduce" : 0,
            "output" : 3
    },
    "ok" : 1
}

这实际上只是选择"独特的东西"作为发出的_id值,而不是任何具体的东西,因为这一切实际上只是不同文档上的值之间的差异。

全局变量通常是这些类型的"配对"聚合或生成"运行总计"的解决方案。现在,聚合框架无法访问全局变量,尽管它很可能是一个不错的选择。mapReduce框架有它们,所以可以公平地说,它们也应该可用于聚合框架。

现在他们不是,所以坚持使用mapReduce。

相关内容

  • 没有找到相关文章

最新更新