1

Я пытаюсь объединить два поля здесь моя коллекцияобъединить два поля в объект

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

Теперь я хочу, чтобы объединить Phone и Email в 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(); 

API объединенных операций в обоих случаях поможет уменьшить нагрузку ввода-вывода на сервере, отправив запросы только один раз в каждые 500 документов в процессе обработки коллекции.

+0

Но как обновить таблицу – raja

+0

@raja Добавлена ​​операция обновления – chridam

Смежные вопросы