Firestore transaction with multiple get

前端 未结 3 1523
一个人的身影
一个人的身影 2021-02-13 05:13

I\'m trying to run a transaction with a variable number of read operations. I put the read () operations before than update ().

Reading the Firestore doc on https://clou

3条回答
  •  时光取名叫无心
    2021-02-13 05:40

    I couldn't figure out how to do this in pure Typescript, but I was able to find a JavaScript example that uses promises, so I adapted that to fit my needs. It seems to be working correctly, however when I run my function rapidly (by clicking on a button in rapid succession) I get console errors that read POST https://firestore.googleapis.com/v1beta1/projects/myprojectname/databases/(default)/documents:commit 400 (). I am unclear on whether those are errors I should be worried about, or if they're simply a a result of the transaction retrying. I posted my own question about that, and am hopeful to get some answers on it. In the meantime, here is the code that I came up with:

    async vote(username, recipeId, direction) {
    
      let value;
    
      if ( direction == 'up' ) {
        value = 1;
      }
    
      if ( direction == 'down' ) {
        value = -1;
      }
    
      // assemble vote object to be recorded in votes collection
      const voteObj: Vote = { username: username, recipeId: recipeId , value: value };
    
      // get references to both vote and recipe documents
      const voteDocRef = this.afs.doc(`votes/${username}_${recipeId}`).ref;
      const recipeDocRef = this.afs.doc('recipes/' + recipeId).ref;
    
      await this.afs.firestore.runTransaction( async t => {
    
        const voteDoc = await t.get(voteDocRef);
        const recipeDoc = await t.get(recipeDocRef);
        const currentRecipeScore = await recipeDoc.get('score');
    
        if (!voteDoc.exists) {
    
          // This is a new vote, so add it to the votes collection
          // and apply its value to the recipe's score
          t.set(voteDocRef, voteObj);
          t.update(recipeDocRef, { score: (currentRecipeScore + value) });
    
        } else {
    
          const voteData = voteDoc.data();
    
          if ( voteData.value == value ) {
    
            // existing vote is the same as the button that was pressed, so delete
            // the vote document and revert the vote from the recipe's score
            t.delete(voteDocRef);
            t.update(recipeDocRef, { score: (currentRecipeScore - value) });
    
          } else {
    
            // existing vote is the opposite of the one pressed, so update the
            // vote doc, then apply it to the recipe's score by doubling it.
            // For example, if the current score is 1 and the user reverses their
            // +1 vote by pressing -1, we apply -2 so the score will become -1.
            t.set(voteDocRef, voteObj);
            t.update(recipeDocRef, { score: (currentRecipeScore + (value*2))});
          }
    
        }
    
        return Promise.resolve(true);
    
      });
    
    }
    

提交回复
热议问题