更新 MongoDB 中的嵌套数组

Update nested array in MongoDB

我正在尝试在 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 内并正确搜索我的字段中的数据,问题只是更新不起作用。

谢谢!

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

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

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

还建议了其他小改动:

  • getCollection('person') 而不是 getCollection('Person')
  • 查找命令中缺少 square/curly 括号: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();