1

in my node app, I need to add 2 elements to an array 'roles', which belongs to collection 'users'. I'm using native mongodb driver. Here is my code:

MongoClient.connect(url, function (err, db) {
            if (err) {
                console.log('Unable to connect to the mongoDB server. Error:', err);
            } else {
                console.log('Connection established to', url);

                var collection = db.collection('users');

                var roles = req.body.requestedRoles.split(',');

                roles.forEach(function(role){
                    collection.update(
                        {
                            email: req.body.userEmail
                        },
                        {
                            $push: { roles: role }
                        },
                        {upsert: true},
                        function(err, result) {
                            if (err) {
                                console.log('err:  ' + err);
                            }
                            else {
                                console.log('update result:  ' + result);
                            }
                        }
                    );
                });

                collection.update(
                    {
                        email: req.body.userEmail
                    },
                    {
                         $push: { roles: req.body.requestedRoles }
                    },
                    {upsert: true},
                    function(err, result) {
                        if (err) {
                            console.log('err:  ' + err);
                        }
                        else {
                            console.log('update result:  ' + result);
                        }
                    }
                );
            }
        });

req.body.requestedRoles contains "role-1,role-2"

When this code runs, I end up with the following 3 (instead of 2) roles: 'role-1', 'role-2', 'role-1,role-2'

Obviously, I do not need that third entry. What can I change to avoid this?

2 Answers 2

1

You have a collection.update(...) after the roles.forEach as well as the one inside the forEach callback. That's causing the push of role-1,role-2, so remove it!

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

Comments

1

Presuming that the first line of code here actually correctly "splits" an array then you can just add the $each modifier to $push:

    var roles = req.body.requestedRoles.split(',');
    collection.update(
        { "email": req.body.userEmail  },
        {  "$push": { "roles": { "$each": roles } } },
        { "upsert": true },
        function(err, result) {
            if (err) {
               console.log('err:  ' + err);
            }
            else {
                console.log('update result:  ' + result);
            }
        }
    );

This avoids needing to control the loop with callbacks for simply adding multiple elements to an array as it can be done in a single operation.

There is also $pushAll which does work with "singular" array element arguments such as [1,2,3] but this is generally considerred "deprecated" as of MongoDB 2.4 ( quite an old version now ) in favour of using $each, which is the more capable alternative.

Also note that .update() does not return the modfied document, but just tells you what was updated or not. To return the document you want .findOneAndUpdate() in modern driver releases or .findAndModify() which is the general call for that operation ( and others like it ).

Comments

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.