更新MongoDB中的嵌套数组

时间:2016-09-01 14:27:55

标签: arrays mongodb mongodb-query mongo-shell

我正在尝试在mongo shell中进行更新,但我遇到了麻烦。

我有以下json:

{
"_id" : ObjectId("56cc03c16f4e85f538ef79ae"),
"contact_id" : NumberLong(1000295524418),
"gender" : 1,
"phonetic_gender" : 1,
"first_name" : "LEANDRO",
"score" : 44,
"address" : [ 
    {
        "address_id" : NumberLong(2634224807),
        "rank" : 201604.0,
        "score" : 7.0,
        "street_type" : "AV",
        "street_title" : "DA",
        "street" : "EMILIA DE CASTRO MARTINS",
        "number" : 34.0,
        "district" : "JARDIM BELA VISTA",
        "city" : "GUARULHOS",
        "state" : "SP",
        "zip_code" : 7132470.0,
        "create_date" : ISODate("2014-08-07T00:00:00.000Z"),
        "update_date" : ISODate("2016-05-03T00:00:00.000Z")
    }, 
    {
        "address_id" : NumberLong(2634735566),
        "rank" : 201410,
        "score" : 10,
        "street_type" : "AV",
        "street_title" : "DA",
        "street" : "EMILIA DE CASTRO MARTINS",
        "district" : "JARDIM BELA VISTA",
        "city" : "GUARULHOS",
        "state" : "SP",
        "zip_code" : "07132470",
        "create_date" : ISODate("2014-08-07T03:00:00.000Z"),
        "update_date" : ISODate("2014-08-07T03:00:00.000Z")
    }
]}

我需要浏览所有文档并更新地址数组中“rank”和“score”字段的类型。

请参阅我正在执行的以下代码:

var total = 0
var skip = 0
var total_adress = db.company.count() - skip
var bulk = db.person.initializeUnorderedBulkOp()
var person = db.getCollection('Person').find( {$and:[ {"contact_id":1000295524418}).addOption(DBQuery.Option.noTimeout).forEach(
function(person){
        var contact_id = person.contact_id.valueOf()
            bulk.find(
                { contact_id: contact_id  }
            ).update(
                { 
                    $set: {
                        "address.$.zip_code":"address.zip_code".toString(),
                        "address.$.rank": NumberInt("address.rank"),
                        "address.$.number": "address.number".toString(),
                        "address.$.score": NumberInt("address.score") - 2
                    }
                } 
            );


    if((++total % 1000) === 0){
        print("Total person....: " + total_adress)
        print("Iniciando bulk..: " + Date())
        bulk.execute({ w: 0 })
        bulk = db.company.initializeUnorderedBulkOp()
        print("Fim bulk........: " + Date())
        print("#############################################################################")
    }
}); bulk.execute();  print(total);

现在出现了问题,当我在Mongo中运行此命令时,它没有错误。确保它属于foreach并且在字段中正确搜索我的数据,问题只是更新不起作用。

谢谢!

1 个答案:

答案 0 :(得分:1)

人员文档中的地址密钥是一组文档。根据jstell的评论,其中一个解决方案是执行以下步骤:

  • 将地址数组的副本复制为array_of_addresses变量。
  • 遍历array_of_addresses的每个文档并根据需要更新密钥。
  • bulk.find.update管道中,使用新更新的数组address更新array_of_addresses键值。

请注意,find()和批量更新执行之间的地址数组的任何更新都可能被覆盖。

其他一些小改动也表明:

  • getCollection('person')代替getCollection('Person')
  • 在find命令中缺少方括号/花括号:find( {$and:[{"contact_id":1000295524418} ]} )

    var total = 0;
    var skip = 0;
    var bulk = db.person.initializeUnorderedBulkOp();
    db.getCollection('person').find({$and:[{"contact_id"1000295524418}]}).addOption(DBQuery.Option.noTimeout).forEach(
    
       function(person){
    
       //extract the array into array_of_addresses variable
       var contact_id = person.contact_id.valueOf();
       var array_of_addresses = person.address.valueOf() ;
    
       //Loop through the array_of_addresses
       for ( var i = 0; i< array_of_addresses.length ; i++) {
    
       //assign element of array to address variable
         address = array_of_addresses[i];
    
         //DO YOUR MODIFICATIONS HERE. e.g. zipcode
         zip_code = address.zip_code.valueOf().toString();
         address.zip_code = zip_code;
    
        }
      //Set the modified array value to address element of the document
      bulk.find(
          { contact_id: contact_id  }
       ).update(
           {
                $set: {
                address : array_of_addresses
            }
          }
      );
    });
    
    //bulk execute
    bulk.execute();