Flutter product rating system with Firebase Transaction.

Arzuman Mamishov
3 min readJul 18, 2023

--

www.pexels.com

Solution 1:

Do you want to know how to calculate a rating system by using transactions and save it in Firebase Firestore in your next or current Flutter app?

If so, here are my solution 1.

ratingCalculation(String productUid, double rating, String documentId,
) async {
DocumentReference documentReference =
FirebaseFirestore.instance.collection('products').doc(productUid);

await FirebaseFirestore.instance.runTransaction((transaction) async {
DocumentSnapshot documentSnapshot =
await transaction.get(documentReference);

final lastRatingForTheUser = documentSnapshot.data() as Map;
String? newRating;
double? ratingOfUser = double.tryParse(lastRatingForTheUser['rating']);

if (ratingOfUser == 0.0) {
newRating = rating.toStringAsFixed(2);
} else {
double calculateRating = (ratingOfUser! + rating) / 2;
newRating = calculateRating.toStringAsFixed(2);
}

transaction.update(documentReference, {'rating': newRating});
})
}

First of all let me give you short explanation of Transaction in Firebase:

Transactions are useful in scenarios where multiple users might be simultaneously modifying the same data, and you want to avoid conflicts or inconsistencies. Means, if you have ‘like’ system for your product, transaction will get — like field value (like:15 or productRating: 9.9)— from database then will make changes to it. If any concurrent modifications occur during the transaction, Firebase will automatically retry the transaction until it can be successfully applied without conflicts. “Concurrent modification refers to a scenario where multiple users or processes are attempting to modify the same data simultaneously”.

1.Inside our main functions ratingCalculation() to use Transaction we create document reference for our document inside ‘products’ collection.

DocumentReference documentReference =
FirebaseFirestore.instance.collection('products').doc(productUid);

2.Then using runTransaction() method we are starting transaction

await FirebaseFirestore.instance.runTransaction((transaction) async {}

3.We need to retrieve the field value from the database for the specific product that we are going to rate.

DocumentSnapshot documentSnapshot =
await transaction.get(documentReference);

final lastRatingForTheUser = documentSnapshot.data() as Map;
String? newRating;
double? ratingOfUser = double.tryParse(lastRatingForTheUser['rating']);

After retrieving the value from the database, we can use the double.tryParse() method to convert the value from a string type to a double type. This conversion allows us to perform calculations or operations using the numeric value of the field.

4. In the next step, we can use an if condition to check if the current value is equal to 0.0. This indicates that we are getting the first rating for this product. In this case, the rating value should be the exact number that user provide for this product. This condition ensures that we handle the scenario correctly when we get the first rating for the product.

if (ratingOfUser == 0.0) {
// after . sign take only two digits.
newRating = rating.toStringAsFixed(2);
} else {
double calculateRating = (ratingOfUser! + rating) / 2;
newRating = calculateRating.toStringAsFixed(2);
}

Let’s imagine that we received a 3-star rating for our product, and this rating is the first one. If we don’t use an ‘if’ condition, the calculation would be as follows:
(0 + 3) / 2 = 1.5, which is not the desired outcome. Here number 0 comes from database and number 3 we got from user as a rating number.

By using an ‘if’ condition, we can handle this scenario properly and assign the rating value as 3 directly since it is the first rating for the product.

5. By using transaction.update() we update field value in the same document with the calculated rating number

transaction.update(documentReference, {'rating': newRating});

Oleeeeeeeey! The mission is accomplished. Please have patience while I explain the details of the second solution.

--

--

Arzuman Mamishov

I am Founder, Product owner and Flutter developer based in Germany. With a passion for software development, I strive to create innovative solutions.