Transactional updating numeric values in Firebase Realtime Database
I am thinking a lot about my personal projects. When thinking about The High Five Network recently, I figured that I am using the locally cached value of likes of an achievement when someone gives a high five for an achievement. This means, I am taking the locally cached value, increase it by one and store it in the database. The issue is: When several people like the same post at the same time, likes might get lost.
When working with databases in general, we will face the situation where we want to update an existing value. Sometimes it is just replacing an old value with a new one, e.g. the name after marriage and sometimes it is increasing a counter, e.g. a counter of likes. Let's discuss the difference between an update and a transaction and see how this can be done using Firebase.
What is the problem with calling .update() when increasing a counter?
The first scenario is a situation where problems are very unlikely because this update is done once at a time by one person. Once the name is changed, it is changed and will not be changed by someone else in the near future. Even if multiple people update the name of a person at the same time, it won't be a problem because they would write the same name to the database (the new one after marriage).
Increasing a counter is a situation where a simple update does not help because that is something which can be done in parallel by several people. Several people might like the same post at the same time or shortly after another. We cannot rely on the number of likes which is displayed and cached locally in the application. When the two users see that a post has 2 likes and click the like button, this value (2) cannot be just increased by one because this would lead to storing 3 as a result two times whereas the resulting number of likes should be 4 in the end. As you can see, one increment would be missing.
This is where transactions come into play because they are blocking other operations until the statements of the first transaction are executed.
How to update a numeric value in Firebase Realtime Database using a transaction?
When you want to increase a counter using Firebase Realtime Database, you simply need to use the transaction
function instead of the update
function:
const upvotesRef = db.ref('server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes');
upvotesRef.transaction((current_value) => {
return (current_value || 0) + 1;
});
You need to specify the field of the reference you want to change (in this case the upvotes
field of the post with the id -JRHTHaIs-jNPLXOQivY
). Then you need to call the transaction function on that reference. It will select the current value and increase by one, or use 0 and increase by one, if no value is present yet. If several people like the same post at the same time, the transactions will be executed one after another without using the locally cached values but the value which is stored in the database which will then be increased by one.
The documentation of how to use transactions in Firebase Realtime Database can be found here.