2016-03-22 17 views
2

Gibt es eine Möglichkeit, eine verschachtelte Dokumentstruktur in ein Array zu konvertieren? Unten ist ein Beispiel:Mongo konvertiert eingebettetes Dokument in Array

Eingang

"experience" : { 
     "0" : { 
      "duration" : "3 months", 
      "end" : "August 2012", 
      "organization" : { 
       "0" : { 
        "name" : "Bank of China", 
        "profile_url" : "http://www.linkedin.com/company/13801" 
       } 
      }, 
      "start" : "June 2012", 
      "title" : "Intern Analyst" 
     } 
    }, 

Erwartete Ausgabe:

"experience" : [ 
      { 
      "duration" : "3 months", 
      "end" : "August 2012", 
      "organization" : { 
       "0" : { 
        "name" : "Bank of China", 
        "profile_url" : "http://www.linkedin.com/company/13801" 
       } 
      }, 
      "start" : "June 2012", 
      "title" : "Intern Analyst" 
     } 
    ], 

Zeit einen Skript Ich bin mit über jedes Element zu durchlaufen, wandeln sie in ein Array & schließlich Aktualisieren Sie das Dokument. Aber es braucht viel Zeit, gibt es einen besseren Weg, dies zu tun? Siehe

+0

Bitte erwähnen Sie Ihre Mongodb-Version? Erwähnen Sie auch, wenn Sie Ihr Dokument dauerhaft transformieren möchten? – Saleem

Antwort

4

Sie müssen noch über den Inhalt wiederholen, sondern sollten Sie wieder mit Bulk-Operationen schreiben:

Entweder für MongoDB 2.6 und höher:

var bulk = db.collection.initializeUnorderedBulkOp(), 
    count = 0; 

db.collection.find({ 
    "$where": "return !Array.isArray(this.experience)" 
}).forEach(function(doc) { 
    bulk.find({ "_id": doc._id }).updateOne({ 
     "$set": { "experience": [doc.experience["0"]] } 
    }); 
    count++; 

    // Write once in 1000 entries 
    if (count % 1000 == 0) { 
     bulk.execute();  
     bulk = db.collection.initializeUnorderedBulkOp(); 
    } 
}) 

// Write the remaining 
if (count % 1000 != 0) 
    bulk.execute(); 

oder in modernen Versionen von MongoDB 3.2 und höher wird die bulkWrite() Methode bevorzugt:

var ops = []; 

db.collection.find({ 
    "$where": "return !Array.isArray(this.experience)" 
}).forEach(function(doc) { 
    ops.push({ 
     "updateOne": { 
      "filter": { "_id": doc._id }, 
      "update": { "$set": { "experience": [doc.experience["0"]] } } 
     } 
    }); 

    if (ops.length == 1000) { 
     db.collection.bulkWrite(ops,{ "ordered": false }) 
     ops = []; 
    } 
}) 

if (ops.length > 0) 
    db.collection.bulkWrite(ops,{ "ordered": false }); 

Also, wenn Schrift Zurück in die Datenbank über einen Cursor, dann Bulk-Schreib-Operationen mit "ungeordneten" Set ist der Weg zu gehen. Es ist nur eine Schreib/Antwort pro Batch von 1000 Anfragen, was eine Menge Overhead reduziert, und "ungeordnet" bedeutet, dass Schreibvorgänge parallel statt in einer seriellen Reihenfolge stattfinden können. Alles macht es schneller.

0

wenn diese Abfrage mit MongoDB Version funktioniert

Für MongoDB Version 3.2+:

db.doc.aggregate([ 
    {$project:{experience:["$experience.0"]}} 
]) 

MongoDB < 3.2:

db.doc.aggregate([ 
    {$group: {_id:"$_id", experience:{$push:"$experience.0"}}} 
]) 

Es Ihr Dokument in verwandeln sollte:

{ 
    "_id" : ObjectId("56f1b046a65ea8a72c34839c"), 
    "experience" : [ 
     { 
      "duration" : "3 months", 
      "end" : "August 2012", 
      "organization" : { 
       "0" : { 
        "name" : "Bank of China", 
        "profile_url" : "http://www.linkedin.com/company/13801" 
       } 
      }, 
      "start" : "June 2012", 
      "title" : "Intern Analyst" 
     } 
    ] 
} 

Ein besserer Ansatz, wenn Sie Dokumente in der Sammlung dauerhaft mit Aggregation Framework ändern möchten.

Nehmen wir an, Ihr Kollektionsnamen doc

db.doc.aggregate([ 
    {$group: {_id:"$_id", experience:{$push:"$experience.0"}}}, 
    {$out: "doc"} 
]) 

Abfrage ist über alle Ihre Dokumente an Ort und Stelle verwandeln.

+0

Es ist immer noch ein falscher Ansatz, unabhängig von der Version. Du wiederholst immer wieder dasselbe, ohne zu verstehen, was daran falsch ist. –

Verwandte Themen