Matt Langlois
Matt Langlois

Reputation: 305

Get ObjectID of updated document

I'm trying to update a parent document with an array of all of it's children document Ids using an upsert. The problem is the ID is only returned if the upsert caused an insert to occur.

I've got the following code which works when new children are being inserted but once one is updated the promise locks up due to the result's upsertedId being null.

        let promises = [];
        parent.children.forEach(child => {
            //Child contains everything except the _id
            promises.push(database.collection('Children').updateOne(
                child,
                child,
                {
                    upsert: true
                }
            ));
        });

        Promise.all(promises).then(result => {
            delete parent.children;
            parent.childIds = result.map(upsert => new ObjectId(upsert.upsertedId._id)); //ONLY THERE ON INSERT?
            database.collection('Parents').updateOne({
                parentId: obj.parentId
            }, obj, {
                upsert: true
            }).then(() => {
                //some success functionality
            }, error => {
                //some error functionality
            });
        }, error => {
            //some error functionality
        });

Upvotes: 1

Views: 650

Answers (1)

Matt Langlois
Matt Langlois

Reputation: 305

It appears the solution was to use the findOneAndUpdate method. This method will find an object, updated it and then return the document. It also accepts the upsert parameter thus an insert is performed when a specific document is not found.

In the case that an update is performed the result will contain the document under the value field.

In the case that a insert is performed (when upsert is true) a the field lastErrorObject.upserted will be set in the result object and the value field will be null.

Here is the code that fixed my issue:

        let promises = [];
        parent.children.forEach(child => {
            promises.push(database.collection('Children').findOneAndUpdate(
                child,
                child,
                {
                    upsert: true
                }
            ));
        });

        Promise.all(promises).then(result => {
            delete parent.children;
            parent.childrenIds = result.map(upsert => new ObjectID(upsert.lastErrorObject.upserted || upsert.value._id));
            database.collection('Parents').updateOne({
                parentId: parent.parentId
            }, obj, {
                upsert: true
            }).then(() => {
                //some success functionality
            }, error => {
                //some error functionality
            });
        }, error => {
            //some error functionality
        });

Upvotes: 4

Related Questions