MapReduce е бавен, но може да обработва много големи масиви от данни. Рамката за агрегиране от друга страна е малко по-бърза, но ще се затрудни с големи обеми данни.
Проблемът с показаната ви структура е, че трябва да "$unwind" масивите, за да отворите данните. Това означава създаване на нов документ за всеки елемент от масива и с рамката за агрегиране, която трябва да направи това в паметта. Така че, ако имате 1000 документа със 100 елемента на масив, ще трябва да изградите поток от 100 000 документа, за да групирате по и да ги преброите.
Може да искате да обмислите дали има оформление на схема, което ще обслужва заявките ви по-добре, но ако искате да го направите с рамката за агрегиране, ето как можете да го направите (с някои примерни данни, така че целият скрипт да падне в обвивката);
db.so.remove();
db.so.ensureIndex({ "items.sku": 1}, {unique:false});
db.so.insert([
{
_id: 42,
last_modified: ISODate("2012-03-09T20:55:36Z"),
status: 'active',
items: [
{ sku: '00e8da9b', qty: 1, item_details: {} },
{ sku: '0ab42f88', qty: 4, item_details: {} },
{ sku: '0ab42f88', qty: 4, item_details: {} },
{ sku: '0ab42f88', qty: 4, item_details: {} },
]
},
{
_id: 43,
last_modified: ISODate("2012-03-09T20:55:36Z"),
status: 'active',
items: [
{ sku: '00e8da9b', qty: 1, item_details: {} },
{ sku: '0ab42f88', qty: 4, item_details: {} },
]
},
]);
db.so.runCommand("aggregate", {
pipeline: [
{ // optional filter to exclude inactive elements - can be removed
// you'll want an index on this if you use it too
$match: { status: "active" }
},
// unwind creates a doc for every array element
{ $unwind: "$items" },
{
$group: {
// group by unique SKU, but you only wanted to count a SKU once per doc id
_id: { _id: "$_id", sku: "$items.sku" },
}
},
{
$group: {
// group by unique SKU, and count them
_id: { sku:"$_id.sku" },
doc_count: { $sum: 1 },
}
}
]
//,explain:true
})
Обърнете внимание, че направих $groupd два пъти, защото казахте, че SKU може да се брои само веднъж на документ, така че първо трябва да сортираме уникалните двойки doc/sku и след това да ги преброим.
Ако искате резултатът да е малко по-различен (с други думи, ТОЧНО като във вашата извадка), ние можем да ги проектираме.