简体   繁体   中英

Update nested array in MongoDB

I'm trying to do an update here in the mongo shell and I'm having trouble.

I have the following 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")
    }
]}

I need to go through all my documents and update the type of field "rank" and "score" in the address array.

See the following code I'm doing:

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);

Now comes the problem, when I run this command in Mongo it does not error. Have made sure that it falls within the foreach and and search my data in the field correctly, the problem is just the update does not work.

Thank you!

The address key in the person document is an array of documents. Based on jstell's comment, one of the solutions is to perform the following steps:

  • Make a copy of the address array into array_of_addresses variable.
  • Loop through each document of array_of_addresses and update the keys as necessary.
  • In bulk.find.update pipeline, update the address key value with newly updated array array_of_addresses .

Please note, that any update to the address array between find() and the execution of bulk update may be overwritten.

Other minor changes also suggested:

  • getCollection('person') instead of getCollection('Person')
  • Missing square/curly brackets in find command: 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. eg 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(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM