MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Mongodb агрегат на поддокумент в масив

MapReduce е бавен, но може да обработва много големи масиви от данни. Рамката за агрегиране от друга страна е малко по-бърза, но ще се затрудни с големи обеми данни.

Проблемът с показаната ви структура е, че трябва да "$unwind" масивите, за да отворите данните. Това означава създаване на нов документ за всеки елемент от масива и с рамката за агрегиране, която трябва да направи това в паметта. Така че, ако имате 1000 документа със 100 елемента на масив, ще трябва да изградите поток от 100 000 документа, за да групирате по и да ги преброите.

Може да искате да обмислите дали има оформление на схема, което ще обслужва заявките ви по-добре, но ако искате да го направите с рамката за агрегиране, ето как можете да го направите (с някои примерни данни, така че целият скрипт да падне в обвивката);

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

Обърнете внимание, че направих $groupd два пъти, защото казахте, че SKU може да се брои само веднъж на документ, така че първо трябва да сортираме уникалните двойки doc/sku и след това да ги преброим.

Ако искате резултатът да е малко по-различен (с други думи, ТОЧНО като във вашата извадка), ние можем да ги проектираме.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Актуализиране на масив с push и slice

  2. Удостоверяването на командния ред на обвивката на MongoDB е неуспешно

  3. Последователно итериране на курсора mongodb (изчакване на обратни извиквания, преди да преминете към следващия документ)

  4. MongoDB:Как да изтриете всички записи на колекция в MongoDB Shell?

  5. Mongodb различен в поле на масив със заявка за регулярен израз?