构建Firestore事务操作

时间:2018-02-02 19:11:51

标签: angular typescript firebase ionic3 google-cloud-firestore

我在Firestore上有如下所示的删除操作。它工作正常。但是你能告诉我如何使用transaction来做这件事吗?此时如果有任何失败,它会进行部分删除。

  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();
    });
}

1 个答案:

答案 0 :(得分:1)

您必须获取要删除的所有文档引用,然后在事务中使用 Promise.all 遍历每个引用。

如下所示:

  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'))
  }

在您的情况下,您可以将您的功能更改为此代码:

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'))
  }

当然你应该在另一个函数中破坏这个功能,但这样可行。