MapReduce is traag, maar kan zeer grote datasets aan. Het aggregatieraamwerk is daarentegen iets sneller, maar zal moeite hebben met grote datavolumes.
Het probleem met uw getoonde structuur is dat u de arrays moet "$afwikkelen" om de gegevens te openen. Dit betekent dat er voor elk array-item een nieuw document moet worden gemaakt en met het aggregatieraamwerk moet dit in het geheugen worden gedaan. Dus als je 1000 documenten hebt met 100 array-elementen, moet je een stroom van 100.000 documenten opbouwen om ze te groupBy en te tellen.
Je zou kunnen overwegen om te kijken of er een schemalay-out is die je query's beter zal bedienen, maar als je het met het Aggregation-framework wilt doen, kun je dit als volgt doen (met wat voorbeeldgegevens zodat het hele script in de shell valt);
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
})
Merk op dat ik twee keer $group'd heb, omdat je zei dat een SKU maar één keer per document kan tellen, dus we moeten eerst de unieke doc/sku-paren uitzoeken en ze dan optellen.
Als u de uitvoer een beetje anders wilt (met andere woorden, PRECIES zoals in uw voorbeeld), kunnen we ze $projecteren.