MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Ulepszenia struktury agregacji MongoDB 2.6

To gościnny post autorstwa Vlada Mihalcei. Vlad jest architektem oprogramowania pasjonującym się integracją oprogramowania, wysoką skalowalnością i wyzwaniami współbieżności. Oto link do oryginalnego posta.

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.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Wyjaśnienie upsert MongoDB

  2. Samoobsługowa MongoDB

  3. Nieudana inicjalizacja globalna:BadValue Nieprawidłowa wartość lub brak ustawień regionalnych użytkownika. Upewnij się, że zmienne środowiskowe LANG i/lub LC_* są ustawione poprawnie

  4. MongoDB $weeklyUpdate #65 (15 kwietnia 2022):GDELT, Mongoose i czas na Hackathon!

  5. Przegląd narzędzia MongoDB Database Profiler