我有一系列项目,
[ a, b, c, d ]
我想成对分组,例如,
[ [ a, b ], [ b, c ], [ c, d ] ]
这将用于计算原始集合中每个项目之间的差异,但该部分使用多种技术解决,例如this question中的那个。
我知道这可以通过map reduce实现,但我想知道聚合是否可行。
编辑:这是一个例子,
物品的收集;每个项目都是一个实际的文件。
[
{ 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 }
]
答案 0 :(得分: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。