greensmith
greensmith

Reputation: 643

mongoose findOneAndUpdate callback with array of ids

I am using findOneAndUpdate in a forEach loop to create/update multiple entries.

I would like it to return an array of all the object id's it has created or updated.

During the loop, I can see it adding data to the array, but one it leaves the loop, the array is empty.

Should the array not be populated?

here is my code.

var softwareArray = ["Software1","Software2","Software3"],
updatedArray = [];

softwareArray.forEach(function(software){
    Software.findOneAndUpdate(
        {
            Name: software
        },
        {
            Name: software
        },
        {upsert:true},
        function(err, rows){
            updatedArray.push(rows._id);
            console.log(updatedArray); //This has data in it....
        }
    );
});
console.log(updatedArray); //This has no data in it...

Edit: Updated with my working changes for Thiago

var softwareArray = ["Software1","Software2","Software3"],
updatedArray = [];

loopSoftware(softwareArray, function(updatedArray){
    console.log(updatedArray);
    //carry on....
}

function loopSoftware(input, cb){
    var returnData = [];

    var runLoop = function(software, done) {
        Software.findOneAndUpdate(
            {Name: software},
            {Name: software},
            {upsert:true},function(err, rows){
                returnData.push(rows._id);
                done()
            }
        );
    };

    var doneLoop = function(err) {

        cb(returnData);

    };

    async.forEachSeries(input, runLoop, doneLoop);
}

Upvotes: 1

Views: 3759

Answers (2)

TheHippo
TheHippo

Reputation: 63159

I decorated your code to make you see when what is happening:

var softwareArray = ["Software1","Software2","Software3"],
updatedArray = [];

//  TIMESTAMP: 0

softwareArray.forEach(function(software){

    //  TIMESTAMP: 1, 2, 3

    Software.findOneAndUpdate(
        {
            Name: software
        },
        {
            Name: software
        },
        {upsert:true},
        function(err, rows){
            // TIMESTAMP: 5, 6, 7
            updatedArray.push(rows._id);
            console.log(updatedArray); // This has data in it....

            // want to use the result?
            if (updatedArray.length == softwareArray.length) {
                console.log(updatedArray);
            }
        }
    );
});

// TIMESTAMP: 4

console.log(updatedArray);

Upvotes: 1

gustavohenke
gustavohenke

Reputation: 41440

Of course this will happen - just like any other networking on Node, it's asynchronous!

This means that the callback you specified for your findOneAndUpdate operation have not run yet when it reaches the console.log(updatedArray); code.

Take a look at Q for working around this common problem.

Upvotes: 0

Related Questions