sql >> Databasteknik >  >> NoSQL >> MongoDB

Mongodb aggregat på underdokument i array

MapReduce är långsam, men den kan hantera mycket stora datamängder. Aggregationsramverket å andra sidan är lite snabbare, men kommer att kämpa med stora datamängder.

Problemet med din struktur som visas är att du måste "$avveckla" arrayerna för att öppna data. Detta innebär att man skapar ett nytt dokument för varje arrayobjekt och med det aggregeringsramverk som det behöver göra detta i minnet. Så om du har 1000 dokument med 100 arrayelement kommer det att behöva bygga en ström av 100 000 dokument för att gruppera efter och räkna dem.

Du kanske vill överväga att se om det finns en schemalayout som kommer att servera dina frågor bättre, men om du vill göra det med aggregeringsramverket så här kan du göra det (med lite exempeldata så att hela skriptet hamnar i skalet);

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

Observera att jag har $group'd två gånger, eftersom du sa att en SKU bara kan räknas en gång per dokument, så vi måste först sortera ut de unika doc/sku-paren och sedan räkna upp dem.

Om du vill ha utdata lite annorlunda (med andra ord, EXAKT som i ditt exempel) kan vi $projicera dem.



  1. Mongo hittar dubbletter för poster för två eller flera fält

  2. 3 sätt att välja raden med det maximala värdet i SQL

  3. Vad är komplexiteten (Big-O) för att söka efter en indexerad data i mongoDB?

  4. Hur man skapar fält för automatisk ökning