1

我試圖合併兩個領域 這裏是我收集合併兩個領域爲對象

db.Acc_Details.findOne() 
{ 
    "_id": ObjectId("577f43fe748646cc91370713"), 
    "Acc_Id": 1, 
    "Name": "xxxxx", 
    "Phone": NumberLong("123456789"), 
    "Email": "[email protected]" 
} 

現在,我想PhoneEmail合併爲contact和更新這個集合

db.Acc_Details.findOne() 
{ 
    "_id": ObjectId("577f43fe748646cc91370713"), 
    "Acc_Id": 1, 
    "Name": "xxxxx", 
    "Contact": { 
     "Phone": NumberLong("123456789"), 
     "Email": "[email protected]" 
    } 
} 

這是我所嘗試過的,但我不知道它是否正確:

db.Acc_Details.aggregate([ 
    { 
     $project: { 
      "Contact": { 
       "$map": { 
        input: { $literal: ["p1", "p2"] }, 
        as: "p", 
        in: { 
         $cond: [ 
          { $eq: ["$$p", "p1"] }, 
          "$Phone", 
          "$Email" 
         ] 
        } 
       } 
      } 
     } 
    }, 
    { $unwind: "$Contact" } 
]) 

結果是

{ "_id" : ObjectId("577f43fe748646cc91370713"), "Contact" : NumberLong("12356789") } 
{ "_id" : ObjectId("577f43fe748646cc91370713"), "Contact" : "[email protected]" } 

有人可以幫助我?

回答

2

這有點矯枉過正。一個更簡單的管道如下:

db.Acc_Details.aggregate([ 
    { 
     "$project": { 
      "Acc_Id": 1, 
      "Name": 1, 
      "Contact": { 
       "Phone": "$Phone", 
       "Email": "$Email" 
      } 
     } 
    } 
]) 

要使用新架構更新表,你需要利用與bulkWrite() API,它是任務更高效的更新。請看下面的批量更新操作,你只重複使用find()光標並更新領域:

var ops = []; 
db.Acc_Details.find().snapshot().forEach(function(doc) { 
    ops.push({ 
     "updateOne": { 
      "filter": { "_id": doc._id }, 
      "update": { 
       "$set": { 
        "Contact": { "Phone": doc.Phone, "Email": doc.Email } 
       }, 
       "$unset": { "Phone": "", "Email": "" } 
      } 
     } 
    }); 

    if (ops.length === 500) { 
     db.Acc_Details.bulkWrite(ops); 
     ops = []; 
    } 
}) 

if (ops.length > 0) db.Acc_Details.bulkWrite(ops); 

或者使用上述彙總結果:

var ops = []; 
db.Acc_Details.aggregate([ 
    { 
     "$project": { 
      "Contact": { 
       "Phone": "$Phone", 
       "Email": "$Email" 
      } 
     } 
    } 
]).forEach(function(doc) { 
    ops.push({ 
     "updateOne": { 
      "filter": { "_id": doc._id }, 
      "update": { 
       "$set": { "Contact": doc.Contact }, 
       "$unset": { "Phone": "", "Email": "" } 
      } 
     } 
    }); 

    if (ops.length === 500) { 
     db.Acc_Details.bulkWrite(ops); 
     ops = []; 
    } 
}) 

if (ops.length > 0) db.Acc_Details.bulkWrite(ops); 

或者MongoDB的2.6 .x和3.0.x版本使用此版本的Bulk操作:

var bulk = db.Acc_Details.initializeUnorderedBulkOp(), 
    counter = 0; 
db.Acc_Details.find().snapshot().forEach(function(doc) { 
    bulk.find({ "_id": doc._id }).updateOne({ 
     "$set": { 
      "Contact": { "Phone": doc.Phone, "Email": doc.Email } 
     }, 
     "$unset": { "Phone": "", "Email": "" } 
    }); 

    if (counter % 500 === 0) { 
     bulk.execute(); 
     bulk = db.Acc_Details.initializeUnorderedBulkOp(); 
    } 
}); 

if (counter % 1000 !== 0) bulk.execute(); 

在這兩種情況下,Bulk操作API都將通過在要處理的集合中的每個500個文檔中僅發送一次請求來幫助減少服務器上的IO負載。

+0

但是如何更新表 – raja

+0

@raja添加了更新操作 – chridam