I want to delete and create multiple documents in a collection (subcollection) in a single batch, inside a Cloud Function using Firestore Web API. The code inside my Cloud Function looks like this (TypeScript):
const collectionRef = db.collection('my_collection');
const batch = db.batch();
batch.delete(collectionRef.doc('doc01'));
batch.set(collectionRef.doc('doc02'));
await batch.commit();
In my web client, I use react-firebase-hooks
to see collection updates in real time (TypeScript, React.js):
const [docs, loading, error] = useCollectionData(collection(db, 'my_collection'));
The Firestore documentation on transactions & batches states that they should complete their write operations atomically. But this is not what I observe. When I call my Cloud Function, I observe separate updates on the client:
docs
is updated to include both 'doc01' and 'doc02'.docs
is updated again, now without 'doc01'.I also see this in my local Firestore Emulator at http://localhost:4000/firestore/default/data/my_collection
, that doc02
appears in the list a split-second earlier than 'doc01' is removed.
The same happens if I change my Cloud Function code to use transactions:
const collectionRef = db.collection('my_collection');
await db.runTransaction(async (transaction) => {
transaction.delete(collectionRef.doc('doc01'));
transaction.set(collectionRef.doc('doc02'));
});
I want both the delete
and set
to complete together, without seeing any partial results. What am I doing wrong?
It's hard to be certain as you don't actually show the behavior that is problematic, but most likely you're seeing the events for local writes. The Firestore SDK optimistically fires events on the client that performs the writes. You can check if the snapshot metadata has pending writes to catch this condition.