Updating & Deleting
Now that we know how to find documents, how do we change them or delete them?
Saving changes to existing documents
The easiest way to change a document in the database is to use either the replace
or save
method on an altered document.
These methods both write the document to the database,
but replace
will raise an exception when the document does not exist yet, while save
will insert the document.
Using save()
method:
bar = Product.find_one(Product.name == "Mars").run()
bar.price = 10
bar.save()
Otherwise, use the replace()
method, which throws:
- a ValueError
if the document does not have an id
yet, or
- a bunnet.exceptions.DocumentNotFound
if it does, but the id
is not present in the collection
bar.price = 10
try:
bar.replace()
except (ValueError, bunnet.exceptions.DocumentNotFound):
print("Can't replace a non existing document")
Note that these methods require multiple queries to the database and replace the entire document with the new version. A more tailored solution can often be created by applying update queries directly on the database level.
Update queries
Update queries can be performed on the result of a find
or find_one
query,
or on a document that was returned from an earlier query.
Simpler updates can be performed using the set
, inc
, and current_date
methods:
bar = Product.find_one(Product.name == "Mars").run()
bar.set({Product.name:"Gold bar"})
bar = Product.find_all(Product.price > .5).inc({Product.price: 1}).run()
More complex update operations can be performed by calling update()
with an update operator, similar to find queries:
Product.find_one(Product.name == "Tony's").update(Set({Product.price: 3.33})).run()
The whole list of the update query operators can be found here.
Native MongoDB syntax is also supported:
Product.find_one(Product.name == "Tony's").update({"$set": {Product.price: 3.33}}).run()
Upsert
To insert a document when no documents are matched against the search criteria, the upsert
method can be used:
Product.find_one(Product.name == "Tony's").upsert(
Set({Product.price: 3.33}),
on_insert=Product(name="Tony's", price=3.33, category=chocolate)
)
Deleting documents
Deleting objects works just like updating them, you simply call delete()
on the found documents:
bar = Product.find_one(Product.name == "Milka").run()
bar.delete()
Product.find_one(Product.name == "Milka").delete().run()
Product.find(Product.category.name == "Chocolate").delete().run()
Response Type
For the object methods update
and upsert
, you can use the response_type
parameter to specify the type of response.
The options are:
- UpdateResponse.UPDATE_RESULT
- returns the result of the update operation.
- UpdateResponse.NEW_DOCUMENT
- returns the newly updated document.
- UpdateResponse.OLD_DOCUMENT
- returns the document before the update.