我有一个名为" orders"的集合。此集合中的每个订单都有一系列产品ID。例如:
> db.orders.find()
[
{ _id: 1, products: [10, 11, 12] },
{ _id: 2, products: [13, 14] },
{ _id: 3, products: [15] },
{ _id: 4, products: [16, 17] }
]
现在,我想创建一个集合,我将n
个产品组合在一起,每个订单的产品必须在同一个文档中,并且n总是大于产品的数量任何订单。
所以,在上面的示例中,假设我将n
指定为3.结果如下:
[{
orders: [1],
products: [10, 11, 12]
}, {
orders: [2, 3],
products: [13, 14, 15]
}, {
orders: [4],
products: [16, 17]
}]
mongo聚合可以实现吗?
答案 0 :(得分:1)
这实际上并不是你在数组聚合过程中会做的事情。由于您需要跨文档维护值,因此在聚合框架中无法实现。除了"引爆点之外没有自然的分组边界"其中"products"
的总收集元素变为三个或更多值,并且这种累积需要"全局",这是聚合框架无法使用的内容
MapReduce有&#34;全局&#34;,但是当你考虑所涉及的操作时,这并不会减少&#34;任何东西。当然有&#34;积累&#34;,但这只是处理到那个&#34;临界点&#34;的总数据的一个因素。正如刚才提到的。返回的实际数据是&#34;与集合中存储的数据完全相同的<#34; ,但只是以输出格式重新组织。
因此,最好在处理光标&#34;时处理文档中的累积。因此,使用更多项目扩展您的示例数据以说明另一点:
{ "_id" : 1, "products" : [ 10, 11, 12 ] }
{ "_id" : 2, "products" : [ 13, 14 ] }
{ "_id" : 3, "products" : [ 15 ] }
{ "_id" : 4, "products" : [ 16, 17 ] }
{ "_id" : 5, "products" : [ 18, 19 ] }
{ "_id" : 6, "products" : [ 20, 21 ] }
{ "_id" : 7, "products" : [ 22, 23 ] }
然后你基本上处理&#34;光标&#34;结果与逻辑做累积:
var output = {}
db.orders.find().forEach(function(order) {
if ( !output.hasOwnProperty("_id") ) {
output = { "_id": [order._id], products: [] };
} else {
output._id = output._id.concat([order._id]);
}
output.products = output.products.concat(order.products);
if ( output.products.length > 3 ) {
var hold = {};
hold._id = output._id.slice(-1);
hold.products = output.products.slice(-(output.products.length-3));
output.products = output.products.slice(0,3);
printjson(output);
output = hold;
} else if ( output.products.length == 3) {
printjson(output)
output = {};
}
})
if ( Object.keys(output).length != 0 ) {
printjson(output);
}
输出为:
{ "_id" : [ 1 ], "products" : [ 10, 11, 12 ] }
{ "_id" : [ 2, 3 ], "products" : [ 13, 14, 15 ] }
{ "_id" : [ 4, 5 ], "products" : [ 16, 17, 18 ] }
{ "_id" : [ 5, 6 ], "products" : [ 19, 20, 21 ] }
{ "_id" : [ 7 ], "products" : [ 22, 23 ] }
因此输出采用不同的格式&#34;并且&#34;累积&#34;这样所有"products"
数据最多只有三个项目,但实际上它仍然是集合中的相同数据,没有减少 。这是重要的一点。
因此,累积过程需要&#34; global&#34; ,您可以在其中构建累积的_id
值列表以及总计products
。另请注意,由于为[4,5]
累积的数据实际上会超过三个项目,因此剩余的项目将被转移到下一个&#34;分组&#34;中。
现在mapReduce确实有如前所述的&#34; globals&#34; ,但这种文档的累积意味着通常将遗留下来的东西没有&#34;发出&#34;因为总"products"
尚未达到 3 的计数。
mapReduce的情况实际上只是作为服务器上的 JavaScript runnner ,因为这个累积实际上是在&#34; mapper&#34;功能而不是&#34; reducer&#34;。 &#34;减速机的功能&#34;需要&#34;分组键&#34;已在mapper中确定。因此,执行全局累积以获得_id
组合是mappers的工作。
更不用说&#34;集合&#34;输出,MongoDB不喜欢&#34;数组&#34; _id
值,实际上&#34;错误&#34;如果你试试。
所以这不是&#34;服务器聚合&#34; 的真正工作,而是通过处理&#34;游标&#34;来实现天真的工作。无论如何它都是&#34;所有原始数据&#34; 所以它不像在服务器上运行简化返回的数据输出。处理光标。