MapReduce est lent, mais il peut gérer de très grands ensembles de données. Le cadre d'agrégation, en revanche, est un peu plus rapide, mais aura du mal avec de gros volumes de données.
Le problème avec votre structure montrée est que vous devez "$ dérouler" les tableaux pour ouvrir les données. Cela signifie créer un nouveau document pour chaque élément du tableau et avec le cadre d'agrégation, il doit le faire en mémoire. Donc, si vous avez 1000 documents avec 100 éléments de tableau, il faudra créer un flux de 100 000 documents afin de les regrouper et de les compter.
Vous voudrez peut-être envisager de voir s'il existe une disposition de schéma qui servira mieux vos requêtes, mais si vous voulez le faire avec le cadre d'agrégation, voici comment vous pouvez le faire (avec quelques exemples de données pour que le script entier tombe dans le shell);
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
})
Notez que j'ai regroupé $ deux fois, car vous avez dit qu'un SKU ne peut compter qu'une seule fois par document, nous devons donc d'abord trier les paires doc/sku uniques, puis les compter.
Si vous voulez que la sortie soit un peu différente (en d'autres termes, EXACTEMENT comme dans votre échantillon), nous pouvons les $projecter.