【问题标题】:Update nested array in MongoDB更新 MongoDB 中的嵌套数组
【发布时间】:2016-09-01 14:27:54
【问题描述】:

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

谢谢!

【问题讨论】:

  • 您有几个问题。 '$' 位置指示符将仅匹配第一个子文档(请参阅docs.mongodb.com/manual/reference/operator/update/positional)。此外,您不能(无论如何在单个操作中)通过引用它的当前值来更新字段值。您必须先加载文档,捕获现有值,然后执行另一个命令来更新文档。
  • @jstell 你能告诉我吗?

标签: arrays mongodb mongodb-query mongo-shell


【解决方案1】:

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

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

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

还建议进行其他小的更改:

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

【讨论】:

    猜你喜欢
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 2017-09-11
    相关资源
    最近更新 更多