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