Piet
Piet

Reputation: 415

Updating multiple value in array in MongoDB

I receive a jsonObject and want to perfom a Mongo-DB update:

The jsonObject: "tablename":"1","inventar":[{"ean":"802.6180.222"},{"ean":"657.7412.878"}]}

The existing document (shortened):

"tablename": "1",
"accepted": false,
"inventar": [
    {
        "ean": "802.6180.222",
        "accepted": "0"
    },
    {
        "ean": "657.7412.878",
        "accepted": "0"
    }
],

I need to set the accepted value to "1" for each object in the Array (which is in the invetar-jsonObject.)

The Code:

app.post('/in_accept', function(request,response){
var jsonString=request.body.json;
var jsonObj = JSON.parse(jsonString);
var InUser = jsonObj.in_user;
var InDate = jsonObj.in_date;
var inventar = jsonObj.inventar; //is an Array
var tablename = jsonObj.tablename;
console.log(inventar);
var query = {"tablename": tablename};
var update = {"accepted": true, CODE FOR UPDATING INVENTAR};
var options = {"upsert": false, "new": true};
        Move.findOneAndUpdate(query, update, options,
        function(err,Move) {
            console.log( Move );
        });
response.json({"success": true});
});

I know that mongoDB provides the operator "each" but I stuck on the whole syntax. For each "ean" the accepted value should be set on "1".

Thanks

Upvotes: 1

Views: 202

Answers (1)

Blakes Seven
Blakes Seven

Reputation: 50436

The only real "sane" way to do this aside of retrieving the object via .findOne() or variant then making modfications in code and calling .save() ( which is not considered "sane" as the concurency issues juyst make that approach "mental' ), is to perform "multiple" updates, or essentially one for each array member you want to change.

Your "best" approach is to gig into the core driver right now and get access to the Bulk Operations API methods:

var input = { "tablename":"1","inventar":[{"ean":"802.6180.222"},{"ean":"657.7412.878"}]},
    bulk = Move.collection.initializeOrderedBulkOp();

// Build the statements
input.inventar.forEach(function(inventar) {
    bulk.find({ 
       "tablename": input.tablename,
       "inventar.ean": inventar.ean
    }).updateOne({
        "$set": { "inventar.$.accepted": 1 }
    });
});

// Then execute
bulk.execute(function(err,result) {
   if (!err) {
      response.json({ "sucess": true })
   } else {
      // handle error
   }
})

That makes sure that both requests are sent to the server at the same time in a single request and only one response.

Each "query" from the .find() matches an element in the array and returns it's "index" value via the positional $ operator, which is used in the "update" portion of the method to $set the value at the matched index position.

Upvotes: 1

Related Questions