Firebase Realtime Database and Cloud Functions — increment counter based on data nodes












1














I'm working on a web application that will visualize data from my Firebase database. But first, I want to be able to "count" the total number of users with a given data so that I can then use that count number in my graphs.



For reference, my database looks like this:



enter image description here



Because I expect separate totals for the required keys, I'm guessing that I'll need separate counters for each one. I've started writing a cloud function to keep track of when a new user is created:



import * as functions from 'firebase-functions'
export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()

const afterGrad = userData.afterGrad
const gender = userData.gender
const gradDate = userData.gradDate
const program = userData.program
const race = userData.race
const timeToComplete = userData.timeToComplete
})


But now, I'm extremely lost at how I should go about creating counters. Would something like this suffice, with an individual counter for each constant?



import * as functions from 'firebase-functions'
var counterAfterGrad;

export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad
var counterAfterGrad++
})


Or should I be thinking about using a transaction in this case? I'm really not sure of the best way, and would really appreciate some help.










share|improve this question
























  • increase count while creating user
    – Har Kal
    Nov 20 '18 at 15:48
















1














I'm working on a web application that will visualize data from my Firebase database. But first, I want to be able to "count" the total number of users with a given data so that I can then use that count number in my graphs.



For reference, my database looks like this:



enter image description here



Because I expect separate totals for the required keys, I'm guessing that I'll need separate counters for each one. I've started writing a cloud function to keep track of when a new user is created:



import * as functions from 'firebase-functions'
export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()

const afterGrad = userData.afterGrad
const gender = userData.gender
const gradDate = userData.gradDate
const program = userData.program
const race = userData.race
const timeToComplete = userData.timeToComplete
})


But now, I'm extremely lost at how I should go about creating counters. Would something like this suffice, with an individual counter for each constant?



import * as functions from 'firebase-functions'
var counterAfterGrad;

export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad
var counterAfterGrad++
})


Or should I be thinking about using a transaction in this case? I'm really not sure of the best way, and would really appreciate some help.










share|improve this question
























  • increase count while creating user
    – Har Kal
    Nov 20 '18 at 15:48














1












1








1







I'm working on a web application that will visualize data from my Firebase database. But first, I want to be able to "count" the total number of users with a given data so that I can then use that count number in my graphs.



For reference, my database looks like this:



enter image description here



Because I expect separate totals for the required keys, I'm guessing that I'll need separate counters for each one. I've started writing a cloud function to keep track of when a new user is created:



import * as functions from 'firebase-functions'
export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()

const afterGrad = userData.afterGrad
const gender = userData.gender
const gradDate = userData.gradDate
const program = userData.program
const race = userData.race
const timeToComplete = userData.timeToComplete
})


But now, I'm extremely lost at how I should go about creating counters. Would something like this suffice, with an individual counter for each constant?



import * as functions from 'firebase-functions'
var counterAfterGrad;

export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad
var counterAfterGrad++
})


Or should I be thinking about using a transaction in this case? I'm really not sure of the best way, and would really appreciate some help.










share|improve this question















I'm working on a web application that will visualize data from my Firebase database. But first, I want to be able to "count" the total number of users with a given data so that I can then use that count number in my graphs.



For reference, my database looks like this:



enter image description here



Because I expect separate totals for the required keys, I'm guessing that I'll need separate counters for each one. I've started writing a cloud function to keep track of when a new user is created:



import * as functions from 'firebase-functions'
export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()

const afterGrad = userData.afterGrad
const gender = userData.gender
const gradDate = userData.gradDate
const program = userData.program
const race = userData.race
const timeToComplete = userData.timeToComplete
})


But now, I'm extremely lost at how I should go about creating counters. Would something like this suffice, with an individual counter for each constant?



import * as functions from 'firebase-functions'
var counterAfterGrad;

export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad
var counterAfterGrad++
})


Or should I be thinking about using a transaction in this case? I'm really not sure of the best way, and would really appreciate some help.







javascript firebase firebase-realtime-database google-cloud-functions counter






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 '18 at 15:50







gbm0102

















asked Nov 20 '18 at 15:43









gbm0102gbm0102

395




395












  • increase count while creating user
    – Har Kal
    Nov 20 '18 at 15:48


















  • increase count while creating user
    – Har Kal
    Nov 20 '18 at 15:48
















increase count while creating user
– Har Kal
Nov 20 '18 at 15:48




increase count while creating user
– Har Kal
Nov 20 '18 at 15:48












1 Answer
1






active

oldest

votes


















3














Yes, you should use a transaction. See the documentation here: https://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactions and https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction



For counting the overall number of users you could do as follows:



export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad

const allUsersCounterRef = admin
.database()
.ref('allUsersCounter');

return allUsersCounterRef
.transaction(counter_value => {
return (counter_value || 0) + 1;
})

})


Note that you may have to take into consideration the deletion of a user.



You could very well have several counters, for example by "gender" (male/female) and by "program". You would then use an object in the transaction as follows:



exports.onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val();

const countersRef = admin.database().ref('counters');

return countersRef.transaction(currentData => {
currentData[userData.gender] = (currentData[userData.gender] || 0) + 1;
currentData[userData.program] = (currentData[userData.program] || 0) + 1;
return currentData;
});
});





share|improve this answer























  • Thanks! Quick question: is .ref('genderCounters/' + userData.gender) assuming that, in my database, I also have a child for genderCounters outside/under my students child?
    – gbm0102
    Nov 20 '18 at 16:16










  • .ref('genderCounters/' + userData.gender) would create a counter for a root node genderCounters/male and a counter for a root node genderCounters/female. You could use .ref('students/genderCounters/' + userData.gender)
    – Renaud Tarnec
    Nov 20 '18 at 16:19












  • I see. And if I wanted to reference these counters in other parts of my code (for my data visualization), I would simply need to reference the counter value at, for example, genderCounters/male?
    – gbm0102
    Nov 20 '18 at 16:22










  • Yes indeed, value of genderCounters/male
    – Renaud Tarnec
    Nov 20 '18 at 16:24






  • 1




    @gbm0102 Actually there was an error in my first version of the multi-counters code: I was chaining two transactions while the update of all the counters shall be done in ONE transaction! With the new code you will find the number of "males" under the counters/male node.
    – Renaud Tarnec
    Nov 20 '18 at 18:03











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53396592%2ffirebase-realtime-database-and-cloud-functions-increment-counter-based-on-dat%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














Yes, you should use a transaction. See the documentation here: https://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactions and https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction



For counting the overall number of users you could do as follows:



export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad

const allUsersCounterRef = admin
.database()
.ref('allUsersCounter');

return allUsersCounterRef
.transaction(counter_value => {
return (counter_value || 0) + 1;
})

})


Note that you may have to take into consideration the deletion of a user.



You could very well have several counters, for example by "gender" (male/female) and by "program". You would then use an object in the transaction as follows:



exports.onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val();

const countersRef = admin.database().ref('counters');

return countersRef.transaction(currentData => {
currentData[userData.gender] = (currentData[userData.gender] || 0) + 1;
currentData[userData.program] = (currentData[userData.program] || 0) + 1;
return currentData;
});
});





share|improve this answer























  • Thanks! Quick question: is .ref('genderCounters/' + userData.gender) assuming that, in my database, I also have a child for genderCounters outside/under my students child?
    – gbm0102
    Nov 20 '18 at 16:16










  • .ref('genderCounters/' + userData.gender) would create a counter for a root node genderCounters/male and a counter for a root node genderCounters/female. You could use .ref('students/genderCounters/' + userData.gender)
    – Renaud Tarnec
    Nov 20 '18 at 16:19












  • I see. And if I wanted to reference these counters in other parts of my code (for my data visualization), I would simply need to reference the counter value at, for example, genderCounters/male?
    – gbm0102
    Nov 20 '18 at 16:22










  • Yes indeed, value of genderCounters/male
    – Renaud Tarnec
    Nov 20 '18 at 16:24






  • 1




    @gbm0102 Actually there was an error in my first version of the multi-counters code: I was chaining two transactions while the update of all the counters shall be done in ONE transaction! With the new code you will find the number of "males" under the counters/male node.
    – Renaud Tarnec
    Nov 20 '18 at 18:03
















3














Yes, you should use a transaction. See the documentation here: https://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactions and https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction



For counting the overall number of users you could do as follows:



export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad

const allUsersCounterRef = admin
.database()
.ref('allUsersCounter');

return allUsersCounterRef
.transaction(counter_value => {
return (counter_value || 0) + 1;
})

})


Note that you may have to take into consideration the deletion of a user.



You could very well have several counters, for example by "gender" (male/female) and by "program". You would then use an object in the transaction as follows:



exports.onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val();

const countersRef = admin.database().ref('counters');

return countersRef.transaction(currentData => {
currentData[userData.gender] = (currentData[userData.gender] || 0) + 1;
currentData[userData.program] = (currentData[userData.program] || 0) + 1;
return currentData;
});
});





share|improve this answer























  • Thanks! Quick question: is .ref('genderCounters/' + userData.gender) assuming that, in my database, I also have a child for genderCounters outside/under my students child?
    – gbm0102
    Nov 20 '18 at 16:16










  • .ref('genderCounters/' + userData.gender) would create a counter for a root node genderCounters/male and a counter for a root node genderCounters/female. You could use .ref('students/genderCounters/' + userData.gender)
    – Renaud Tarnec
    Nov 20 '18 at 16:19












  • I see. And if I wanted to reference these counters in other parts of my code (for my data visualization), I would simply need to reference the counter value at, for example, genderCounters/male?
    – gbm0102
    Nov 20 '18 at 16:22










  • Yes indeed, value of genderCounters/male
    – Renaud Tarnec
    Nov 20 '18 at 16:24






  • 1




    @gbm0102 Actually there was an error in my first version of the multi-counters code: I was chaining two transactions while the update of all the counters shall be done in ONE transaction! With the new code you will find the number of "males" under the counters/male node.
    – Renaud Tarnec
    Nov 20 '18 at 18:03














3












3








3






Yes, you should use a transaction. See the documentation here: https://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactions and https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction



For counting the overall number of users you could do as follows:



export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad

const allUsersCounterRef = admin
.database()
.ref('allUsersCounter');

return allUsersCounterRef
.transaction(counter_value => {
return (counter_value || 0) + 1;
})

})


Note that you may have to take into consideration the deletion of a user.



You could very well have several counters, for example by "gender" (male/female) and by "program". You would then use an object in the transaction as follows:



exports.onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val();

const countersRef = admin.database().ref('counters');

return countersRef.transaction(currentData => {
currentData[userData.gender] = (currentData[userData.gender] || 0) + 1;
currentData[userData.program] = (currentData[userData.program] || 0) + 1;
return currentData;
});
});





share|improve this answer














Yes, you should use a transaction. See the documentation here: https://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactions and https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction



For counting the overall number of users you could do as follows:



export const onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val()
const afterGrad = userData.afterGrad

const allUsersCounterRef = admin
.database()
.ref('allUsersCounter');

return allUsersCounterRef
.transaction(counter_value => {
return (counter_value || 0) + 1;
})

})


Note that you may have to take into consideration the deletion of a user.



You could very well have several counters, for example by "gender" (male/female) and by "program". You would then use an object in the transaction as follows:



exports.onMessageCreate = functions.database
.ref('/students/{studentID}')
.onCreate((snapshot, context) => {
const userData = snapshot.val();

const countersRef = admin.database().ref('counters');

return countersRef.transaction(currentData => {
currentData[userData.gender] = (currentData[userData.gender] || 0) + 1;
currentData[userData.program] = (currentData[userData.program] || 0) + 1;
return currentData;
});
});






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 20 '18 at 18:00

























answered Nov 20 '18 at 15:55









Renaud TarnecRenaud Tarnec

10.3k21431




10.3k21431












  • Thanks! Quick question: is .ref('genderCounters/' + userData.gender) assuming that, in my database, I also have a child for genderCounters outside/under my students child?
    – gbm0102
    Nov 20 '18 at 16:16










  • .ref('genderCounters/' + userData.gender) would create a counter for a root node genderCounters/male and a counter for a root node genderCounters/female. You could use .ref('students/genderCounters/' + userData.gender)
    – Renaud Tarnec
    Nov 20 '18 at 16:19












  • I see. And if I wanted to reference these counters in other parts of my code (for my data visualization), I would simply need to reference the counter value at, for example, genderCounters/male?
    – gbm0102
    Nov 20 '18 at 16:22










  • Yes indeed, value of genderCounters/male
    – Renaud Tarnec
    Nov 20 '18 at 16:24






  • 1




    @gbm0102 Actually there was an error in my first version of the multi-counters code: I was chaining two transactions while the update of all the counters shall be done in ONE transaction! With the new code you will find the number of "males" under the counters/male node.
    – Renaud Tarnec
    Nov 20 '18 at 18:03


















  • Thanks! Quick question: is .ref('genderCounters/' + userData.gender) assuming that, in my database, I also have a child for genderCounters outside/under my students child?
    – gbm0102
    Nov 20 '18 at 16:16










  • .ref('genderCounters/' + userData.gender) would create a counter for a root node genderCounters/male and a counter for a root node genderCounters/female. You could use .ref('students/genderCounters/' + userData.gender)
    – Renaud Tarnec
    Nov 20 '18 at 16:19












  • I see. And if I wanted to reference these counters in other parts of my code (for my data visualization), I would simply need to reference the counter value at, for example, genderCounters/male?
    – gbm0102
    Nov 20 '18 at 16:22










  • Yes indeed, value of genderCounters/male
    – Renaud Tarnec
    Nov 20 '18 at 16:24






  • 1




    @gbm0102 Actually there was an error in my first version of the multi-counters code: I was chaining two transactions while the update of all the counters shall be done in ONE transaction! With the new code you will find the number of "males" under the counters/male node.
    – Renaud Tarnec
    Nov 20 '18 at 18:03
















Thanks! Quick question: is .ref('genderCounters/' + userData.gender) assuming that, in my database, I also have a child for genderCounters outside/under my students child?
– gbm0102
Nov 20 '18 at 16:16




Thanks! Quick question: is .ref('genderCounters/' + userData.gender) assuming that, in my database, I also have a child for genderCounters outside/under my students child?
– gbm0102
Nov 20 '18 at 16:16












.ref('genderCounters/' + userData.gender) would create a counter for a root node genderCounters/male and a counter for a root node genderCounters/female. You could use .ref('students/genderCounters/' + userData.gender)
– Renaud Tarnec
Nov 20 '18 at 16:19






.ref('genderCounters/' + userData.gender) would create a counter for a root node genderCounters/male and a counter for a root node genderCounters/female. You could use .ref('students/genderCounters/' + userData.gender)
– Renaud Tarnec
Nov 20 '18 at 16:19














I see. And if I wanted to reference these counters in other parts of my code (for my data visualization), I would simply need to reference the counter value at, for example, genderCounters/male?
– gbm0102
Nov 20 '18 at 16:22




I see. And if I wanted to reference these counters in other parts of my code (for my data visualization), I would simply need to reference the counter value at, for example, genderCounters/male?
– gbm0102
Nov 20 '18 at 16:22












Yes indeed, value of genderCounters/male
– Renaud Tarnec
Nov 20 '18 at 16:24




Yes indeed, value of genderCounters/male
– Renaud Tarnec
Nov 20 '18 at 16:24




1




1




@gbm0102 Actually there was an error in my first version of the multi-counters code: I was chaining two transactions while the update of all the counters shall be done in ONE transaction! With the new code you will find the number of "males" under the counters/male node.
– Renaud Tarnec
Nov 20 '18 at 18:03




@gbm0102 Actually there was an error in my first version of the multi-counters code: I was chaining two transactions while the update of all the counters shall be done in ONE transaction! With the new code you will find the number of "males" under the counters/male node.
– Renaud Tarnec
Nov 20 '18 at 18:03


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53396592%2ffirebase-realtime-database-and-cloud-functions-increment-counter-based-on-dat%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

RAC Tourist Trophy