12

For incrementing an int value in my database , I first get that value by using a listener , increment it by 1 and then set the new value to database. This works but I want to know if there is an easier way of doing this. This way seems like too much work.

adjuremods
  • 2,938
  • 2
  • 12
  • 17

3 Answers3

21

Update: since early 2020 there actually is a server-side operation to increment values in the Realtime Database. See dfeverx's answer on this, or my own Q&A comparing performance between transactions and increments: How quickly can you atomically increment a value on the Firebase Realtime Database?.


There is no server-side way to increment values (or do other calculations) in the Firebase Database.

Your approach is one way of doing this, but it has the chance of leading to a race condition.

  1. the value in the database is 12
  2. client 1 reads the value 12
  3. client 2 read the value 12
  4. client 1 writes its incremented value 13
  5. client 2 writes its incremented value 13

The result is now likely incorrect (it depends on your use-case).

In that case, one way to make it work is to use Firebase transactions, which combine the reading and writing into a single function.

Transactions are covered in the Firebase Database documentation. I highly recommend reading it. A few hours spent there will prevent many problems down the road. From the docs:

postRef.runTransaction(new Transaction.Handler() {
    @Override
    public Transaction.Result doTransaction(MutableData mutableData) {
        Long value = mutableData.getValue(Long.class);
        if (value == null) {
            mutableData.setValue(0);
        }
        else {
            mutableData.setValue(value + 1);
        }

        return Transaction.success(mutableData);
    }

    @Override
    public void onComplete(DatabaseError databaseError, boolean b,
                           DataSnapshot dataSnapshot) {
        Log.d(TAG, "transaction:onComplete:" + databaseError);
    }
});
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
21

From firebase JavaScript SDK v7.14.0 you can use ServerValue.increment() to increment value in firebase

Method 1

var userRef= firebase.database().ref("user/user_id_123");
userRef.push({
  likes: firebase.database.ServerValue.increment(1)
});

Method 2

firebase.database()
    .ref('user')
    .child('user_id_123')
    .child('likes')
    .set(firebase.database.ServerValue.increment(1))

You can also pass float or negative value to the increment function

You can find the reference here: https://firebase.google.com/docs/reference/js/v8/firebase.database.ServerValue

ilbonte
  • 151
  • 1
  • 2
  • 10
d-feverx
  • 1,424
  • 3
  • 16
  • 31
0

Kotlin Version:

val ref = Firebase.database.reference
    .child("users")
    .child(postId)
    .child("likes")

ref.runTransaction(object : Transaction.Handler {

    override fun doTransaction(mutableData: MutableData): Transaction.Result {

        val value = mutableData.getValue(Long::class.java)

        if (value == null) {
            mutableData.value = 0
        } else {
            mutableData.value = value + 1 // to decrement - mutableData.value = value - 1
        }

        return Transaction.success(mutableData)
    }

    override fun onComplete(error: DatabaseError?, committed: Boolean, currentData: DataSnapshot?) {

        if (error != null) {
            println("transaction-onCompleteError: ${error.message}")
        }

        val currentCount = currentData?.getValue(Long::class.java) ?: 0L
        println("currentCount: $currentCount")
    }
})
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256