0

I'm building a step counter app. I got an iOS app that pushes the sum of each day to /users/{mobile}/steps/{date}/ When a new steps child is updated or added, I want to sum the value of all the steps for that particular user and update his stepsTotal.

To achieve that I need to

  1. Find the original user and sum all the steps.
  2. Save the new value to stepsTotal.

I would be most grateful if someone could give some help here. :-)

database

{

  "users": {
    "92291000": {
      "firstName": "Tore",
      "stepsTotal": "1500",
      "steps": {
        "02-09-2017": "500",
        "03-09-2017": "1000"
      },

import.js

var db       = admin.database();
var dbRoot   = db.ref("/");
var usersRef = dbRoot.child("users");

// This works    
function saveUser(attributes) {
  let mobile =  attributes.mobile;
  delete attributes['mobile']
  let user = usersRef.child(mobile);
  user.update(attributes);
}


function increaseSteps( { mobile=null, steps=null } = {}) {
  // Find the User
  console.log("looking for mobile", mobile);  // OK
  let userRef = usersRef.child(mobile);

  // Here I'm not able to read the old data from the user.
  userRef.transaction(function(user) {
    console.log("user: ", user);  // null
    // ^ User is null. 
  });


/*  
  If I mangage to find user above, I expect to do something like this. 
  Or it is possible to only update *stepsTotal*?
*/

  let attributes = {
    firstName: user.firstName,
    lastName: user.lastName,
    stepsTotal: user.stepsTotal + steps,
  }
  user.update( attributes );
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
martins
  • 9,669
  • 11
  • 57
  • 85

1 Answers1

0

If I understand correctly, you have a problem in this snippet of the code:

let userRef = usersRef.child(mobile);

// Here I'm not able to read the old data from the user.
userRef.transaction(function(user) {
  console.log("user: ", user);  // null
  // ^ User is null. 
});

In Firebase Database transactions the initial value is often null. From the Firebase documentation on transactions:

Transaction Function is Called Multiple Times

Your transaction handler is called multiple times and must be able to handle null data. Even if there is existing data in your database it may not be locally cached when the transaction function is run.

This is due to how Firebase transactions work behind the scenes. To learn more about that, see my answers here Transcation updateFunction parameter is null and Firebase runTransaction not working.

The solution is to handle both cases: if the user node doesn't exist yet count the initial number of steps, otherwise update the number of steps:

let userRef = usersRef.child(mobile);

userRef.transaction(function(user) {
  return (user || 0) + new_steps_for_user;
});
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807