Reputation: 65870
I have a delete operation as shown below on Firestore. It is working fine. But could you tell me how can I use a transaction
for doing that? At this moment if there is any failure it does partial delete.
async delete(project: DtoProject): Promise<void> {
await this.fireStore.doc<Project>(`projects/${project.id}/`).delete();
const budgetGroupsQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/budgetGroups`).get();//budgetGroups
budgetGroupsQuerySnapshot.forEach(async (doc: any) => {
await this.fireStore.doc<BudgetGroup>(`projects/${project.id}/budgetGroups/${doc.id}`).delete();
});
const budgetsQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/budgets`).get();//budgets
budgetsQuerySnapshot.forEach(async (doc: any) => {
await this.fireStore.doc<Budget>(`projects/${project.id}/budgets/${doc.id}`).delete();
});
const categoriesQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/categories`).get();//categories
categoriesQuerySnapshot.forEach(async (doc: any) => {
await this.fireStore.doc<Category>(`projects/${project.id}/categories/${doc.id}`).delete();
});
const transactionsQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/transactions`).get();//transactions
transactionsQuerySnapshot.forEach(async (doc: any) => {
const notesQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/transactions/${doc.id}/notes`).get();//notes
notesQuerySnapshot.forEach(async (n: any) => {
await this.fireStore.doc<Note>(`projects/${project.id}/transactions/${doc.id}/notes/${n.id}`).delete();
});
const photosQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/transactions/${doc.id}/photos`).get();//photos
photosQuerySnapshot.forEach(async (p: any) => {
await this.fireStore.doc<Photo>(`projects/${project.id}/transactions/${doc.id}/photos/${p.id}`).delete();
});
await this.fireStore.doc<Transaction>(`projects/${project.id}/transactions/${doc.id}`).delete();
});
}
Upvotes: 2
Views: 454
Reputation: 2592
You have to get all the doc references that you want to delete and then iterate through each one them using Promise.all in the transaction.
Like below:
deleteAll(arrayOfDocReferencesToBeDeleted){
return this.db.runTransaction(async transaction => {
return Promise.all(arrayOfDocReferencesToBeDeleted.map(async (ref) => {
await transaction.delete(ref);
}));
}).then(() => console.log('success')).catch(() => console.log('error'))
}
In your case you can change your function to this code:
async delete(project: DtoProject): Promise<void> {
//first get all the doc referencs that you want to delete
var firstReferenceToBeDelete = this.fireStore.doc<Project>(`projects/${project.id}/`);
//get all the docs from the collection
const budgetGroupsQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/budgetGroups`).get();//budgetGroups
//map the doc references to an array
var groupsRef = budgetGroupsQuerySnapshot.docs.map((doc) => { return this.fireStore.doc<BudgetGroup>(`projects/${project.id}/budgetGroups/${doc.id}`) });
//repeat it until you have all the doc references that you want to delete
const budgetsQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/budgets`).get();//budgets
var budgetsRef = budgetsQuerySnapshot.docs.map((doc) => { return this.fireStore.doc<Budget>(`projects/${project.id}/budgets/${doc.id}`) });
const categoriesQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/categories`).get();//categories
var categoriesRef = categoriesQuerySnapshot.docs.map((doc) => { return this.fireStore.doc<Category>(`projects/${project.id}/categories/${doc.id}`) });
const transactionsQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/transactions`).get();//transactions
var notesRef = [];
var photosRef = [];
var lastRefs = [];
transactionsQuerySnapshot.forEach(async (doc: any) => {
const notesQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/transactions/${doc.id}/notes`).get();//notes
var notes = notesQuerySnapshot.docs.map((note) => {
return this.fireStore.doc<Note>(`projects/${project.id}/transactions/${doc.id}/notes/${note.id}`)
});
notesRef.concat(notes);
const photosQuerySnapshot = await this.authenticationProvider.firestoreDb.collection(`projects/${project.id}/transactions/${doc.id}/photos`).get();//photos
var photos = photosQuerySnapshot.docs.map((photo) => { return this.fireStore.doc<Photo>(`projects/${project.id}/transactions/${doc.id}/photos/${photo.id}`) });
photosRef.concat(photos);
lastRefs.push(this.fireStore.doc<Transaction>(`projects/${project.id}/transactions/${doc.id}`));
});
//make a single array with them
var arrayOfDocReferencesToBeDeleted = [firstReferenceToBeDelete].concat(groupsRef, budgetsRef, categoriesRef, notesRef, photosRef, lastRefs)
//after you have an array with all your doc references you can iterate them in the transaction
return this.db.runTransaction(async transaction => {
return Promise.all(arrayOfDocReferencesToBeDeleted.map(async (ref) => {
await transaction.delete(ref);
}));
}).then(() => console.log('success')).catch(() => console.log('error'))
}
Of course you should break this function in another functions but this will work.
Upvotes: 1