1

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

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

thank you, is working like epxected. Everytime I use MongoDB much deeper, its horrible. So much api around it...
@Piet I personally find it quite simple. Much as if I know I regularly wish to update multiple things such as you want here then I either accept the multiple update process like above or use another collection which I can just update with { "multi": true }.I depends on what works best for me. I have many years of SQL Relational experience ( not young ), and I use NoSQL solutions like MongoDB to better fit the cases where the relational model does not apply. Otherwise I use a relational engine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.