MongoDB si sta evolvendo rapidamente. La versione 2.2 ha introdotto il framework di aggregazione come alternativa al modello di query Map-Reduce. La generazione di report aggregati è un requisito ricorrente per i sistemi aziendali e MongoDB brilla in questo senso. Se sei un principiante, potresti voler controllare questa introduzione al framework di aggregazione o l'ottimizzazione delle prestazioni e le guide alla modellazione dei dati.
Riutilizziamo il modello di dati che ho introdotto per la prima volta durante la dimostrazione delle velocissime capacità di inserimento di MongoDB:
{ "_id" : ObjectId("5298a5a03b3f4220588fe57c"), "created_on" : ISODate("2012-04-22T01:09:53Z"), "value" : 0.1647851116706831 }
Miglioramenti all'aggregazione di MongoDB 2.6
Nella versione 2.4, se eseguo la seguente query di aggregazione:
db.randomData.aggregate( [ { $match: { "created_on" : { $gte : new Date(Date.UTC(2012, 0, 1)), $lte : new Date(Date.UTC(2012, 0, 10)) } } }, { $group: { _id : { "minute" : { $minute : "$created_on" } }, "values": { $addToSet: "$value" } } }]);
Ho raggiunto la limitazione dei risultati di aggregazione di 16 MB:
{ "errmsg" : "exception: aggregation result exceeds maximum document size (16MB)", "code" : 16389, "ok" : 0 }
I documenti MongoDB sono limitati a 16 MB e prima della versione 2.6, il risultato dell'aggregazione era un documento BSON. La versione 2.6 lo ha invece sostituito con un cursore.
Eseguendo la stessa query su 2.6 si ottiene il seguente risultato:
db.randomData.aggregate( [ { $match: { "created_on" : { $gte : new Date(Date.UTC(2012, 0, 1)), $lte : new Date(Date.UTC(2012, 0, 10)) } } }, { $group: { _id : { "minute" : { $minute : "$created_on" } }, "values": { $addToSet: "$value" } } }]) .objsLeftInBatch(); 14
Ho utilizzato il metodo objsLeftInBatch basato sul cursore per testare il tipo di risultato dell'aggregazione e la limitazione di 16 MB non si applica più al risultato complessivo. I risultati interni del cursore sono normali documenti BSON, quindi sono ancora limitati a 16 MB, ma questo è molto più gestibile rispetto al precedente limite di risultato complessivo.
La versione 2.6 affronta anche le limitazioni della memoria di aggregazione. Una scansione completa della raccolta come:
db.randomData.aggregate( [ { $group: { _id : { "minute" : { $minute : "$created_on" } }, "values": { $addToSet: "$value" } } }]) .objsLeftInBatch();
può finire con il seguente errore:
{ "errmsg" : "exception: Exceeded memory limit for $group, but didn't allow external sort. Pass allowDiskUse:true to opt in.", "code" : 16945, "ok" : 0 }
Quindi, ora possiamo eseguire operazioni di ordinamento di grandi dimensioni utilizzando il parametro allowDiskUse:
db.randomData.aggregate( [ { $group: { _id : { "minute" : { $minute : "$created_on" } }, "values": { $addToSet: "$value" } } }] , { allowDiskUse : true }) .objsLeftInBatch();
La versione 2.6 ci consente di salvare il risultato dell'aggregazione in una raccolta diversa utilizzando la fase $out appena aggiunta.
db.randomData.aggregate( [ { $match: { "created_on" : { $gte : new Date(Date.UTC(2012, 0, 1)), $lte : new Date(Date.UTC(2012, 0, 10)) } } }, { $group: { _id : { "minute" : { $minute : "$created_on" } }, "values": { $addToSet: "$value" } } }, { $out : "randomAggregates" } ]); db.randomAggregates.count(); 60
Sono stati aggiunti nuovi operatori come let, map, cond, solo per citarne alcuni.
L'esempio successivo aggiungerà AM o PM alle informazioni sull'ora di ogni voce di evento specifico.
var dataSet = db.randomData.aggregate( [ { $match: { "created_on" : { $gte : new Date(Date.UTC(2012, 0, 1)), $lte : new Date(Date.UTC(2012, 0, 2)) } } }, { $project: { "clock" : { $let: { vars: { "hour": { $substr: ["$created_on", 11, -1] }, "am_pm": { $cond: { if: { $lt: [ {$hour : "$created_on" }, 12 ] } , then: 'AM',else: 'PM'} } }, in: { $concat: [ "$$hour", " ", "$$am_pm"] } } } } }, { $limit : 10 } ]); dataSet.forEach(function(document) { printjson(document); });
Risultato:
"clock" : "16:07:14 PM" "clock" : "22:14:42 PM" "clock" : "21:46:12 PM" "clock" : "03:35:00 AM" "clock" : "04:14:20 AM" "clock" : "03:41:39 AM" "clock" : "17:08:35 PM" "clock" : "18:44:02 PM" "clock" : "19:36:07 PM" "clock" : "07:37:55 AM"
Conclusione
La versione MongoDB 2.6 include molti altri miglioramenti come operazioni in blocco o intersezione di indici. MongoDB è in continua evoluzione, offrendo una valida alternativa per l'archiviazione basata su documenti. Con un tale ritmo di sviluppo, non c'è da stupirsi che sia stato nominato database dell'anno 2013.