Reputation: 99
How can I update a mongo document with the following requirements:
Find a document by email property:
If the document exists:
If the document doesn't exist
The findOneAndUpdate
seems not to convey the both 3 of the requirements. Thanks.
Upvotes: 1
Views: 14695
Reputation: 1
await Order.updateOne({ _id: item._id }, { $set: { orderNumber: generateRandomNumber(12) }}, { upsert: true });
You can do like this.
Upvotes: 0
Reputation: 386
My recommendation is to go the following path:
db.getCollection('<some-collection>').update(
{ email: '[email protected]' },
{
$set: {
name: "some guy",
username: someguy,
tel: '1234'
}
},
{ upsert: true }
);
Check upsert documentation: https://docs.mongodb.com/manual/reference/method/db.collection.update/#upsert-option
Lets go through your requirements now:
3. If the document doesn't exist, insert the new document.
Yes, it will insert new document to collection if it doesnt find the document by email. Resulting document will be combination of find condition + $set + autogenerated _id, so it will look something like this:
{
_id: ObjectId(...)
email: '[email protected]'
name: "some guy",
username: someguy,
tel: '1234'
}
2. If retrieved document property A is null or undefined or doesn't exist, update using property A of the new object.
All properties provided in $set
will unconditionally be persisted in the database, which also covers your requirement of updating null/undefined values
3. If both retrieved and new document have property A, keep property A (the retrieved one).
If both newly provided A
and database A
are the same, we dont have a problem.
If A
s are different, dont you want to store the new A
value?
If you are afraid of nulls/undefined values, you can omit them before providing object to $set.
What is the use-case for you not wanting to update database property with newly provided value?
One use-case i can see is that you want to pass createdAt
in case you are creating new record, but dont want to update that value for existing records.
If thats the case, and you know those properties in advance, you can use $setOnInsert
update operator. https://docs.mongodb.com/manual/reference/operator/update/#id1
So your update query can look like this:
db.getCollection('<some-collection>').update(
{ email: '[email protected]' },
{
$set: {
name: "some guy",
username: someguy,
tel: '1234'
},
$setOnInsert: {
createdAt: new Date(),
updatedAt: new Date()
}
},
{ upsert: true }
);
I hope this helps!
Upvotes: 12
Reputation: 2173
You need not retrieve the document for updating the property A. You can use the update
API of mongo to do so. Please find the psuedo code below:
db.<collection>.update({
"$or": [
{ "PropertyA": { "$exists": false } },
{ "PropertyA": null }
]
}, {$set: {"PropertyA": "NewValue"}});
The above code is for one property, but I think you can figure out how to scale it up.
Hope this helps !!
Upvotes: 3