2017-06-07 6 views
0

Angenommen, ich habe Dokumente wie dieseein verschachteltes Objekt in MongoDB und benennen

{ 
    "id" : "1415166669", 
    "color" : { 
     "14" : "Silver" 
    }, 
    "name":"Random Name" 
} 

, wo der Schlüssel innen Farbe ändern kann, dh Nächstes Dokument aussehen wie diese

{ 
    "id" : "1415126969", 
    "color" : { 
     "11" : "Gold" 
    }, 
    "name":"Random Name 2" 
} 

Ich mag abzuzuflachen und benennen sie sie so, dass meine Dokumente, die eine ähnliche Struktur haben wie folgt:

{ 
    "id" : "1415126969", 
    "color" : "Gold" 
    "name":"Random Name 2" 
} 

und

{ 
    "id" : "1415166669", 
    "color" : "Silver" 
    "name":"Random Name" 
} 

Ich habe versucht, die Aggregation-Pipeline, aber ich bin mir nicht sicher, wie Sie weiter vorgehen. Auch kann jemand eine Möglichkeit, mit Robomongo vorschlagen, die auch schön sein würde.

+0

Wenn Sie die Werte in Ihrer Sammlung beabsichtigen, ändern, dann eine einfache Schleife in Code ist die bester Ansatz. Dies ist im Aggregation-Framework mit MongoDB 3.4 möglich, aber es ist auch viel komplexer als der Code, der in einer Schleife ausgeführt wird. Das gesamte Aggregations-Framework kann auch mit "$ out" in eine "neue" Sammlung schreiben. Sie sollten diese Methode also nur verwenden, wenn die Sammlung wirklich groß ist. –

Antwort

1

würde ich eine einfache JavaScript-Schleife für diese laufen, da es ganz schnell und einfach zu Code sein wird. Es kann auch auf die gleiche Sammlung angewendet werden:

var ops = []; 

db.collection.find().forEach(function(doc) { 
    let color; 
    Object.keys(doc.color).forEach(function(key) { 
    color = doc.color[key]; 
    }); 
    ops = [ 
    ...ops, 
    { "updateOne": { 
     "filter": { "_id": doc._id }, 
     "update": { "$set": { "color": color } } 
    }} 
    ]; 
    if (ops.length >= 500) { 
    db.collection.bulkWrite(ops); 
    ops = []; 
    } 
}) 

if (ops.length > 0) { 
    db.collection.bulkWrite(ops); 
    ops = []; 
} 

So durchqueren Sie im Grunde die „Schlüssel“ des Objekts und den Wert erhalten, der später wir mit $set

Alternativ zu dem Dokument zurück schreiben, da MongoDB 3.4 Sie können eine Aggregationsanweisung mit $objectToArray ausführen, um auf die Schlüssel zuzugreifen. Aber das sollten Sie nur tun, wenn die Sammlung Millionen von Dokumenten enthält. Die Anforderungen an $out bedeutet das Ergebnis in neue Kollektion ist, und nicht die aktuelle aktualisiert:

db.collecion.aggregate([ 
    { "$addFields": { 
    "color": { 
    "$arrayElemAt": [ 
     { "$map": { 
     "input": { "$objectToArray": "$color" }, 
     "as": "c", 
     "in": "$$c.v" 
     }}, 
     0 
    ] 
    } 
    }}, 
    { "$out": "newcollection" } 
]) 

Das funktioniert, weil $objectToArray macht Ihre Struktur wie folgt aus:

"color": { "11": "Gold" } 

In diese:

"color": [{ "k": "11", "v": "Gold" }] 

So können wir dann den Operator $map verwenden, um den Pfadpfad "color.v" undzu extrahieren, um dies in einen singulären Wert anstatt in ein Array zu verwandeln. Im Allgemeinen sind solche Konvertierungen für Aggregationspipeline-Anweisungen sehr viel komplexer als für das, was Sie einfach erreichen können, indem Sie die Dokumentstruktur im Code manipulieren und dann in die Zielsammlung zurückschreiben.


Angesichts der bestehenden Dokumente:

{ 
     "_id" : ObjectId("59389951fc04695e84e7f4ae"), 
     "id" : "1415166669", 
     "color" : { 
       "14" : "Silver" 
     }, 
     "name" : "Random Name" 
} 
{ 
     "_id" : ObjectId("59389a75fc04695e84e7f4af"), 
     "id" : "1415126969", 
     "color" : { 
       "11" : "Gold" 
     }, 
     "name" : "Random Name 2" 
} 

Ausgabe von beiden Methoden ist:

{ 
     "_id" : ObjectId("59389951fc04695e84e7f4ae"), 
     "id" : "1415166669", 
     "color" : "Silver", 
     "name" : "Random Name" 
} 
{ 
     "_id" : ObjectId("59389a75fc04695e84e7f4af"), 
     "id" : "1415126969", 
     "color" : "Gold", 
     "name" : "Random Name 2" 
} 
+0

Ich bin ziemlich neu zu mongodb und ich weiß nicht viel über Java-Skript, so kann ich nicht debuggen, aber beide Methoden produzieren Fehler. Ich habe versucht, die JavaScript-Funktion auf Robomongo-Shell und es gab den Fehler der unerwarteten Zeichen in Zeile 6 (PS: - Ich aktualisierte die falsche Klammer Problem) und die Aggregat-Pipeline-Methode zeigt einen Fehler, der AddFields ist kein korrekte Methode –

+0

Und das ist, weil ich Mongo 3.2 laufen lasse, so benutzte ich das Update-Feld wie unten db.suggestion_collection.find ({}). forEach (Funktion (Post)) { db.suggestion_collection.update ( {_id: post ._id}, {$ Satz: { Farbe: { "$ arrayElemAt": [{ "$ Karte": { "Eingang": { "$ objectToArray": "$ Farbe"}, "als": "c", "in": "$$ c.v" }}, 0 ] }} } ) }); –

+0

Aber es stürzte nach der Konvertierung nur ein paar Werte Und das auch nicht im gewünschten Format, aber {color: {"0": "Black"}} –

Verwandte Themen