Continuing the discussion from Unofficial Anvil Firebase Integration v0.1🔥:
I am trying to implement a transaction with the following function:
def add_data(self,data,uid):
transaction = fs.transaction() #THIS LINE RAISES AN ERROR
doc1_ref = fs.doc(fs.db,'collection_1',uid)
doc2_ref = fs.doc(fs.db,'collection_2','<uid>')
doc2=transaction.get(doc2_ref)
count = doc2[1]['counter']
transaction.update(doc1_ref,{'count':count})
transaction.update(doc2_ref,{'counter':count+1})
return True
But I get an error stating fire store does not have a transaction attribute.
Looking at the documentation (Linked above) the transaction instance in the example doesn’t show how the object is instantiated.
here is the example:
doc_ref1 = fs.doc(fs.db,'test_collection','uid1')
doc_ref2 = fs.doc(fs.db,'test_collection','uid2')
#read from doc 1
doc1 = transaction.get(doc_ref1)
#write to doc 2
transaction.update(doc_ref2, { 'new_value': 1234 })
The example in the firestore documentation:
transaction = db.transaction()
city_ref = db.collection("cities").document("SF")
@firestore.transactional
def update_in_transaction(transaction, city_ref):
snapshot = city_ref.get(transaction=transaction)
new_population = snapshot.get("population") + 1
...
Do I need to use the transactional decorator? and how do I instantiate the transaction object?
HI @anthonys,
I updated the docs with an up to date transaction example.
Basically, what you do is give a function to the run_transaction method and this function will then be executed as a transaction.
Docs
new_order_dict = {'name':'my example order'}
def add_new_order(transaction):
#get the document which stores the order ids
order_id_ref = fs.doc(fs.db,'ids','current_order_number')
order_id_doc = transaction.get(order_id_ref)
#calculate the next free order id and write it to the dict
next_order_id = order_id_doc.data()['count'] + 1
new_order_dict['id'] = next_order_id
#save new order document
new_order_ref = fs.doc(fs.db,'orders')
transaction.set(new_order_ref,new_order_dict)
#increment the order id for the next order
transaction.update(order_id_ref,{'count': fs.increment(1)})
#Run the above database operations in a transaction
fs.run_transaction(add_new_order)```
2 Likes
This is my EXACT use case
Thank you very much @mark.breuss
I get the following error on the transaction.set
call, but I do not get this error when adding the document without the transcation.
FirebaseError: [code=invalid-argument]: Function Transaction.set() called with invalid data. Unsupported field value: a custom constructor object (found in document transactions
I suspect it has something to do with using datetime objects in the transaction, but I not entirely sure. I ran the transactions with a simply dictionary like the example above and it worked.
Are there other data manipulation being done when adding a document using firestore.add_doc
that isn’t done when using transaction.set
?
The reason for that is that you are essentially calling a javascript function, thus datetimes are not serialized automatically.
The reason why you don’t get an errror for normal updates is that the library takes care of the conversion.
Good thing is that these helper methods are exposed and you can convert them manually.
You can use:
fs.utility.to_proxy({})
To convert a python dict with to a js dict that handles the datetime conversions.