Reputation: 137
I'm pretty new in mongodb so here's my question, what I want is check if the main document exists and then if it does, check if the nested document exist then update it and if it doesn't insert a new one. But with this code I can only update an existent nested document but I cannot create a new one. I don't even know if it is a proper use of this method, is it efficient?
collection.find_one_and_update(
{"_id:{"field1":val1,"field2":val2,"field3":val3,"field4":val4}},
{"$set":{"elements.$[element].prop2":valToUpdate}},
return_document=ReturnDocument.AFTER,
array_filters=[{"element.prop1":valToCheck}],
upsert=True
)
In mongo syntax I think is something like this:
db.collection.findOneAndUpdate(
{"_id:{"field1":val1,"field2":val2,"field3":val3,"field4":val4}},
{"$set":{"elements.$[element].prop2":valToUpdate}},
{ arrayFilters: [ {"element.prop1":valToCheck} ] }
)
Can I use a single function like this one for do the whole process (check if the main and the nested document exist and if it does update, otherwise create a new one)?
A sample of how I want to alter the document:
before execute the method
{
"_id":{"name":"Storename","location":"somewhere","phone":46284723},
"books":
[
{"name":"somebook","price":{"$numberDouble":"34"}}
]
}
After the execution if there's the nested document
{
"_id":{"name":"Storename","location":"somewhere","phone":46284723},
"books":
[
{"name":"somebook","price":{"$numberDouble":"55"}},
]
}
After the execution if there's not the nested document
{
"_id":{"name":"Storename","location":"somewhere","phone":46284723},
"books":
[
{"name":"somebook","price":{"$numberDouble":"34"}},
{"name":"someOTHERbook","price":{"$numberDouble":"45"}}
]
}
Upvotes: 2
Views: 1344
Reputation: 17915
That's because upsert
seems to not work along with $
operator, Also in general upsert is on document level but should not be used to insert missing elements of an array like this scenario. As the actual document exists in DB it will through an error of duplicate _id
.
If you wanted to do this in one DB call, then the below query should work for your scenario, as at any given case only one updateOne
should update the array :
Mongo Query :
db.yourCollectionName.bulkWrite([
{
updateOne: {
filter: {
"_id": {
"name": "Storename",
"location": "somewhere",
"phone": 46284723
}, 'books.name': 'somebook'
}, update: {
$set: { "books.$.price": 100 }
}
}
},
{
updateOne: {
filter: {
"_id": {
"name": "Storename",
"location": "somewhere",
"phone": 46284723,
}
}, update: {
$addToSet: { 'books': { 'name': 'somebook', "price": 100 } }
}
}
}])
Python Code :
import pymongo
from pymongo import UpdateOne
bulkArr = [
UpdateOne({
"_id": {
"name": "Storename",
"location": "somewhere",
"phone": 46284723
}, 'books.name': 'somebook'
}, { '$set': { "books.$.price": 100 } }),
UpdateOne({
"_id": {
"name": "Storename",
"location": "somewhere",
"phone": 46284723,
}
}, {
$addToSet: { 'books': { 'name': 'somebook', "price": 100 } }
})
]
db.yourCollectionName.bulk_write(bulkArr)
PyMongo Ref : Please do refer this link to convert this query. PyMongo-bulk_write
Upvotes: 2