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

Agregat Mongodb na poddokumencie w tablicy

MapReduce jest powolny, ale może obsługiwać bardzo duże zestawy danych. Z drugiej strony framework agregacji jest nieco szybszy, ale będzie miał problemy z dużymi ilościami danych.

Problem z pokazaną strukturą polega na tym, że musisz "$rozwinąć" tablice, aby otworzyć dane. Oznacza to utworzenie nowego dokumentu dla każdego elementu tablicy i za pomocą struktury agregacji, która musi to zrobić w pamięci. Więc jeśli masz 1000 dokumentów ze 100 elementami tablicy, będziesz musiał zbudować strumień 100 000 dokumentów, aby pogrupować według i je policzyć.

Możesz rozważyć sprawdzenie, czy istnieje układ schematu, który lepiej obsłuży Twoje zapytania, ale jeśli chcesz to zrobić za pomocą frameworka Aggregation, oto jak możesz to zrobić (z kilkoma przykładowymi danymi, aby cały skrypt wpadł do powłoki);

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
})

Zwróć uwagę, że podzieliłem $grupę dwa razy, ponieważ powiedziałeś, że jednostka SKU może być liczona tylko raz na dokument, więc najpierw musimy posortować unikalne pary dokumentów/sku, a następnie je policzyć.

Jeśli chcesz, aby wynik był nieco inny (innymi słowy, DOKŁADNIE tak, jak w twoim przykładzie), możemy je $zaprojektować.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. jak pracować z wieloma akcjami i liczyć za pomocą mongodb?

  2. Jak działa parametr arrayFilters w MongoDB

  3. Zaktualizuj wiele dokumentów i zwróć wszystkie zaktualizowane dokumenty

  4. Kompilacje indeksu MongoDB — zapobieganie uruchamianiu nowych kompilacji przez użytkowników

  5. Jak sprawdzić, czy wybrany adres e-mail i nazwa już istnieją w MongoDB?