In Mongoose, I am seeking to perform atomically a way to Model.FindOne-Or-Insert()
, similar functionality and signature as currently available Model.FindOneAndUpdate()
except if an instance exists (i.e. matches filter
) then do not update using provided object
but return instance found as is, and if not exists (i.e. no match with filter
) then insert object
and return new instance.
I could not find a way using Model.FindOneAndUpdate()
not to perform an update to an existing instance by trying out variances to its options
and not providing fields to object
that preferred not to update if instance exists.
So, my current non-atomic workaround is Model.FindOne()
and if not found then perform Document.save()
.
const Foo = DB.model('foo', FooSchema)
async function findOneAndUpdateFoo(jsonFoo, next) {
const filter = {
deletedAt: null
}
if (jsonFoo.dsAccountId) {
filter.dsAccountId = jsonFoo.dsAccountId
}
if (jsonIntegration.dsUserId) {
filter.dsUserId = jsonIntegration.dsUserId
}
if (jsonFoo.providerId) {
filter.providerId = jsonFoo.providerId
}
const fooDoc = {
name: jsonFoo.name,
dsAccountId: jsonFoo.dsAccountId,
dsUserId: jsonFoo.dsUserId,
providerId: jsonFoo.providerId,
providerName: jsonFoo.providerName,
// Most of these fields could be empty
accessToken: jsonFoo.accessToken,
refreshToken: jsonFoo.refreshToken,
scope: jsonFoo.scope,
tokenType: jsonFoo.tokenType,
expiresAt: jsonFoo.expiresAt
}
return await Foo.findOneAndUpdate(
filter, // find a document with that filter
fooDoc, // document to insert when nothing was found
{ upsert: true, new: true, runValidators: true } // options
)
.catch(next)
}
Suggestions? Thank you