Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angularfire2 best way to increment a value?

I searched in many forums, questions, in doc but can't find the correct solution.

Problem

What is the best way to increment a value using angularfire2 ?
I saw we could use [transaction()][] but it's not for angularfire2 actually. Or with snapshot ?

user.service.ts

incrementLike(userToIncrementLike){
    this.af.database.object('users/' + userToIncrementLike.uid).subscribe((userObject) => {
      var newUser = {
        likes: userObject.likes + 1
        };

     });
     this.af.database.object('users/' + userToIncrementLike.uid).update(newUser);

  }

I tried also in this way :

incrementLike(userToIncrementLike){

    let obs = this.af.database.object('users/' + userToIncrementLike.uid);
    obs.subscribe((snapshot) => {
      let newValue = (snapshot.$value) ? (snapshot.$value + 1) : 1;
      obs.set(newValue);
    });
  }

Thank you very much for your help and tips :) Luis.

like image 913
luiswill Avatar asked Mar 04 '17 13:03

luiswill


3 Answers

Firestore now has increment() which correctly increments a field even if multiple users are competing to edit at the same time

Incrementing Values Atomically with Cloud Firestore

To use this in angularfire2

import { firestore } from 'firebase/app';

incrementLike(userToIncrementLike) {
    const increment = firestore.FieldValue.increment(1);
    const userLike = this.af.doc(`users/${userToIncrementLike.uid}`);
    userLike.update({ likes: increment });
}

I used firestore directly since I couldn't find FieldValue in angularfire2.

like image 190
Nabel Avatar answered Nov 12 '22 10:11

Nabel


It isn't necessary to define an object or to use the update() method. The object already exists in the database, so you can just work on it there. This is actually the purpose of transaction()--to work on the data at the data location and therefore prevent conflicts; e.g., two users updating the same value at the same time.

You can also use the template literal in your path if you like. :) (Note the backticks instead of single quotes.)

incrementLike(userToIncrementLike){
    this.af.database.object(`users/${userToIncrementLike.uid}/likes`).query
    .ref.transaction(likes => {
        if (likes === null) {
            return likes = 1;
        } else {
            return likes + 1;
        }
    })
}

Update: September, 2019. Use query instead of $ref.

like image 13
J. Adam Connor Avatar answered Nov 12 '22 10:11

J. Adam Connor


"angularfire2 V5" Solution:

incrementLike(userToIncrementLike){
this.af.database.object(`users/${userToIncrementLike.uid}/likes`)
  .query.ref.transaction((likes => {
    if (likes === null) {
        return likes = 1;
    } else {
        return likes + 1;
    }
})};
like image 5
Sifeng Avatar answered Nov 12 '22 10:11

Sifeng