MapReduce je pomalý, ale dokáže zpracovat velmi velké soubory dat. Na druhou stranu agregační rámec je o něco rychlejší, ale bude bojovat s velkými objemy dat.
Problém s vaší ukázanou strukturou je v tom, že potřebujete "$unwind" pole, abyste otevřeli data. To znamená vytvoření nového dokumentu pro každou položku pole as agregačním rámcem, který to potřebuje, v paměti. Pokud tedy máte 1000 dokumentů se 100 prvky pole, bude potřeba vytvořit proud 100 000 dokumentů, aby je bylo možné seskupit podle a spočítat.
Možná budete chtít zvážit, zda existuje rozvržení schématu, které bude lépe serverovat vaše dotazy, ale pokud to chcete udělat s agregačním rámcem, můžete to udělat takto (s ukázkovými daty, aby se celý skript dostal do shellu);
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
})
Všimněte si, že jsem $group'd dvakrát, protože jste řekl, že SKU se může počítat pouze jednou na dokument, takže musíme nejprve roztřídit jedinečné páry doc/sku a poté je spočítat.
Pokud chcete výstup trochu jiný (jinými slovy, PŘESNĚ jako ve vašem vzorku), můžeme je $promítnout.