0

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!

Jhonathan
  • 330
  • 1
  • 2
  • 14
  • You have several issues. The '$' positional indicator will only match the 1st sub-document (see https://docs.mongodb.com/manual/reference/operator/update/positional/). Also, you cannot (in a single operation, anyway) update a field value by referencing it's current value. You have to load the document first, capture the existing value(s), and execute another command to update the document. – jstell Sep 01 '16 at 15:20
  • @jstell can you show me? – Jhonathan Sep 01 '16 at 16:28

1 Answers1

0

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. 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();
    
Nishant Bhardwaj
  • 638
  • 1
  • 6
  • 13