A. Newbie
A. Newbie

Reputation: 187

Trying to update value in firebase database while listening for changes on another place (Cloud Functions)

I am trying to update the count of the participants in a field in firebase realtime database.
My database looks like this:
root
|_course
|       |_Course1
|            |_descr: "some text"
|            |_lect: "someUID"
|_groups
|        |_Course1
|            |_Group1
|                 |_current: 5
|                 |_others -//-
|_participation
|        |_Course1
|            |_someUID: "Group1"
So now I'm trying to listen for writings on participation/Course1/someUID and when some record shows up I want to update the 'current' field to 6 in groups/Course1/Group1.
So far I've come with:

exports.afterGroupJoined = functions.database.ref('/participation/{courseId}/{uid}').onWrite((change, context) => {
    const writtenContent = change.after.val(); // groupId
    const courseId = context.params.courseId;
    const uid = context.auth ? context.auth.uid : null;

    admin.database().ref('/groups/' + courseId + '/' + writtenContent).once('value').then(snapshot => {
        const count = snapshot.val();
        const current = count+1;
        console.log('User ' + uid + ' joined group ' + writtenContent + ' in course ' + courseId);
        const promise1 = admin.database().ref('/groups/' + courseId + '/' + writtenContent + '/current').set(parseInt(current));
        return Promise.all([promise1]);
    }).catch(err => {
        console.log(err);
      });
});

But what I get is a new child in groups/Course1/Group1 named 'null' with child 'current' having value '0':
root
|_groups
|        |_Course1
|            |_Group1
|            |    |_current: 5
|            |    |_others -//-
|            |_null
|                 |_current: 0
The value of 'current' should've been 6, but I get a new child.
This is from the log:

User fNhAVZUo9QeSbYt0TwBIQmL2mYq1 joined group Group1 in course Course1
Error: Reference.set failed: First argument contains NaN in property 'groups.Course1.Group1.current' at validateFirebaseData

Any help is appreciated.

Upvotes: 0

Views: 389

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598688

It seems like you're reading this JSON:

"Group1": {
  "current": 5
}

Which means you need this code to get the actual count:

const count = snapshot.val().current;

But you're not using anything else from the group, so you might as well just read the count itself. The Promise.all() call also seems unneeded, since you have only one promise. So the entire block could be:

let ref = admin.database().ref('/groups/' + courseId + '/' + writtenContent+'/current');
ref.once('value').then(snapshot => {
    const count = snapshot.val();
    return ref.set(count+1);
}).catch(err => {
    console.log(err);
});

Finally: this approach is susceptible to race conditions if multiple users run the above at almost the same time. You might want to consider using a transaction.

Upvotes: 1

Related Questions