sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB - $project kapslade dokument till rotnivå

För MongoDB 3.6 och senare, använd aggregeringsramverk med en $replaceRoot pipeline som kan tillämpas tillsammans med $mergeObjects operatorn som newRoot uttryck.

Detta uttryck

{ "$mergeObjects": ["$subdoc", "$$ROOT"] }

kommer att slå samman fälten på översta nivån i dokumentet med de i de inbäddade subdoc-fälten så att din sammanlagda operation i slutändan blir som följer:

db.collection.aggregate([
    { "$replaceRoot": { 
        "newRoot": { 
            "$mergeObjects": [ "$subdoc", "$$ROOT" ] 
        } 
    } },
    { "$project": { "subdoc": 0 } }  
])

Annars skulle du behöva en mekanism för att få alla dynamiska nycklar som du behöver för att montera det dynamiska $project dokumentera. Detta är möjligt genom Map-Reduce . Följande mapreduce-operation kommer att fylla en separat samling med alla nycklar som _id värden:

mr = db.runCommand({
    "mapreduce": "my_collection",
    "map" : function() {
        for (var key in this.subdoc) { emit(key, null); }
    },
    "reduce" : function(key, stuff) { return null; }, 
    "out": "my_collection" + "_keys"
})

För att få en lista över alla dynamiska nycklar, kör distinkt på den resulterande samlingen:

db[mr.result].distinct("_id")
["field2", "field3", ...]

Med tanke på listan ovan kan du sätta ihop ditt $project aggregeringspipelinedokument genom att skapa ett objekt som kommer att ha sina egenskaper inställda i en loop. Normalt är ditt $project dokument kommer att ha denna struktur:

var project = {
    "$project": {
        "field1": 1,
        "field2": "$subdoc.field2",
        "field3": "$subdoc.field3"
    }
};

Så genom att använda listan ovan med underdokumentnycklar kan du dynamiskt konstruera ovanstående med JavaScripts reduce() metod:

var subdocKeys = db[mr.result].distinct("_id"),
    obj = subdocKeys.reduce(function (o, v){
      o[v] = "$subdoc." + v;
      return o;
    }, { "field1": 1 }),
    project = { "$project": obj };

db.collection.aggregate([project]);



  1. Node.js, (Hi)Redis och multikommandot

  2. Det går inte att hämta _id-värdet med hjälp av mgo med golang

  3. Vad är JavaScript-motorn som kör mongoDB-skalet?

  4. Hur tar man bort egenskapen för kapslade objekt från MongoDB-dokument?