MongoDB szybko się rozwija. W wersji 2.2 wprowadzono strukturę agregacji jako alternatywę dla modelu zapytań Map-Reduce. Generowanie raportów zagregowanych jest powtarzalnym wymogiem dla systemów korporacyjnych i MongoDB świeci pod tym względem. Jeśli jesteś nowy w tym temacie, możesz zapoznać się z tym wprowadzeniem do struktury agregacji lub z dostrajaniem wydajności i przewodnikami po modelowaniu danych.
Wykorzystajmy ponownie model danych, który po raz pierwszy przedstawiłem, demonstrując niesamowicie szybkie możliwości wstawiania MongoDB:
{ "_id" : ObjectId("5298a5a03b3f4220588fe57c"), "created_on" : ISODate("2012-04-22T01:09:53Z"), "value" : 0.1647851116706831 }
Ulepszenia agregacji MongoDB 2.6
W wersji 2.4, jeśli uruchomię następujące zapytanie agregujące:
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" } } }]);
Osiągnąłem ograniczenie wyniku agregacji 16 MB:
{ "errmsg" : "exception: aggregation result exceeds maximum document size (16MB)", "code" : 16389, "ok" : 0 }
Dokumenty MongoDB są ograniczone do 16 MB, a przed wersją 2.6 wynikiem agregacji był dokument BSON. Wersja 2.6 zastąpiła go kursorem.
Uruchomienie tego samego zapytania w wersji 2.6 daje następujący wynik:
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
Użyłem opartej na kursorze metody objsLeftInBatch, aby przetestować typ wyniku agregacji, a ograniczenie 16 MB nie ma już zastosowania do ogólnego wyniku. Wewnętrzne wyniki kursora to zwykłe dokumenty BSON, dlatego nadal są ograniczone do 16 MB, ale jest to o wiele łatwiejsze w zarządzaniu niż poprzedni ogólny limit wyników.
Wersja 2.6 obejmuje również ograniczenia pamięci agregacji. Pełny skan kolekcji, taki jak:
db.randomData.aggregate( [ { $group: { _id : { "minute" : { $minute : "$created_on" } }, "values": { $addToSet: "$value" } } }]) .objsLeftInBatch();
może skończyć się następującym błędem:
{ "errmsg" : "exception: Exceeded memory limit for $group, but didn't allow external sort. Pass allowDiskUse:true to opt in.", "code" : 16945, "ok" : 0 }
Tak więc możemy teraz wykonywać duże operacje sortowania za pomocą parametru allowDiskUse:
db.randomData.aggregate( [ { $group: { _id : { "minute" : { $minute : "$created_on" } }, "values": { $addToSet: "$value" } } }] , { allowDiskUse : true }) .objsLeftInBatch();
Wersja 2.6 pozwala nam zapisać wynik agregacji w innej kolekcji przy użyciu nowo dodanego etapu $out.
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
Dodano nowe operatory, takie jak let, map, cond, żeby wymienić tylko kilka.
Następny przykład doda AM lub PM do informacji o czasie każdego konkretnego wpisu wydarzenia.
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); });
Wynik:
"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"
Wniosek
Wersja MongoDB 2.6 zawiera wiele innych ulepszeń, takich jak operacje zbiorcze lub przecięcie indeksów. MongoDB stale się rozwija, oferując realną alternatywę dla przechowywania opartego na dokumentach. Przy takim tempie rozwoju nic dziwnego, że została nazwana bazą danych roku 2013.