Google is committed to advancing racial equity for Black communities. See how.

Transactions with Cloud Firestore

In this codelab, you'll enhance a restaurant recommendation web app powered by Cloud Firestore.


This codelab builds on the previous codelabs in this playlist.

If you have not completed part one, Getting started with Cloud Firestore, or part two, Complex queries with Cloud Firestore, please do so before continuing here.

What you'll learn

  • Write data using transactions.

What you'll build

  • Enhancements for our previously built restaurant recommendation app

What you'll need

Before starting this codelab, make sure that you've installed the following:

In this section, you'll add the ability for users to submit reviews of restaurants. So far, all of the write operations in this codelab series have been atomic and relatively simple. If any of the write operations returned an error, the application could just prompt the user to retry or your app could retry the write operation automatically.

Because your app might have many users who want to add a rating for a restaurant, you'll need to coordinate multiple reads and writes. First, the review itself has to be submitted; then the restaurant's rating count and average rating need to be updated. If one of these write operations fails but the other succeeds, then the system could be left in an inconsistent state in which the data in one part of the database doesn't match the data in another.

Fortunately, Cloud Firestore provides transaction functionality that allows multiple reads and writes in a single atomic operation, ensuring that your data remains consistent.

  1. Go back to your file scripts/FriendlyEats.Data.js.
  2. Find the function FriendlyEats.prototype.addRating.
  3. Replace the entire function with the following code:


FriendlyEats.prototype.addRating = function(restaurantID, rating) {
  var collection = firebase.firestore().collection('restaurants');
  var document = collection.doc(restaurantID);
  var newRatingDocument = document.collection('ratings').doc();

  return firebase.firestore().runTransaction(function(transaction) {
    return transaction.get(document).then(function(doc) {
      var data =;

      var newAverage =
          (data.numRatings * data.avgRating + rating.rating) /
          (data.numRatings + 1);

      transaction.update(document, {
        numRatings: data.numRatings + 1,
        avgRating: newAverage
      return transaction.set(newRatingDocument, rating);

In the block above, a transaction is triggered to update the numeric values of averageRating and ratingCount in the restaurant document. At the same time, the new rating is added to the ratings subcollection.