2016-03-22 4 views
2

İç içe geçmiş belge yapısını bir diziye dönüştürmenin bir yolu var mı? Aşağıda bir örnek:Mongo gömülü belgeyi diziye dönüştür

Girdi

"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" 
     } 
    }, 

Beklenen Çıktı:

"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" 
     } 
    ], 

Şu anda, her bir elemanın üzerinde yineleme nihayet bir diziye & onları dönüştürmek için bir komut dosyası kullanıyorum belgeyi güncelleyin. Ama çok zaman alıyor, bunu yapmanın daha iyi bir yolu var mı? < 3,2

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

MongoDB:

: İçine belgenizi dönüştürmek gerekir

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

bu sorgu MongoDB sürümü 3.2+ için lütfen MongoDB sürümü

ile çalışıp çalışmadığını

+0

Lütfen mongodb sürümünüzü anlatın? Ayrıca belgenizi kalıcı olarak dönüştürmek istediğinizden de bahseder misiniz? – Saleem

cevap

4

Hala içeriği üzerinde yinelemek gerekiyor, ama bunun yerine toplu işlemler kullanılarak geri yazılı edilmelidir: MongoDB arasında

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(); 

Veya modern bültenleri: MongoDB 2.6 ve üzeri işletim sistemlerine uygun

Ya 3.2 ve daha büyük, bulkWrite() yöntem tercih edilir: zaman emri Böylece

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

Bir imleç üzerinden veritabanına geri dönerek, daha sonra "unordered" set ile toplu yazma işlemleri gitmek için yoldur. 1000 talepten oluşan her parti için sadece bir yazma/yanıtlama, çok fazla yükü azaltıyor ve "sırasız", yazımların seri bir sıradan ziyade paralel olarak gerçekleşebileceği anlamına geliyor. Hepsi daha hızlı yapar.

0

Bkz
{ 
    "_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" 
     } 
    ] 
} 

Koleksiyondaki belgeleri toplama çerçevesini kullanarak kalıcı olarak değiştirmek istiyorsanız daha iyi bir yaklaşım.

senin koleksiyon adı yerde tüm belgeleri değiştirecek yukarıda doc

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

Sorgu olduğunu varsayalım.

+0

Bu sürümden bağımsız olarak hala yanlış bir yaklaşım. Onun neyin yanlış olduğunu anlamadan aynı şeyi tekrar etmeyi sürdürüyorsun. –