Firebase Realtime Database and Cloud Functions — increment counter based on data nodes
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:
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
add a comment |
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:
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
increase count while creating user
– Har Kal
Nov 20 '18 at 15:48
add a comment |
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:
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
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:
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
javascript firebase firebase-realtime-database google-cloud-functions counter
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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;
});
});
Thanks! Quick question: is.ref('genderCounters/' + userData.gender)
assuming that, in my database, I also have a child for genderCounters outside/under mystudents
child?
– gbm0102
Nov 20 '18 at 16:16
.ref('genderCounters/' + userData.gender)
would create a counter for a root nodegenderCounters/male
and a counter for a root nodegenderCounters/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 ofgenderCounters/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 thecounters/male
node.
– Renaud Tarnec
Nov 20 '18 at 18:03
|
show 1 more comment
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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;
});
});
Thanks! Quick question: is.ref('genderCounters/' + userData.gender)
assuming that, in my database, I also have a child for genderCounters outside/under mystudents
child?
– gbm0102
Nov 20 '18 at 16:16
.ref('genderCounters/' + userData.gender)
would create a counter for a root nodegenderCounters/male
and a counter for a root nodegenderCounters/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 ofgenderCounters/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 thecounters/male
node.
– Renaud Tarnec
Nov 20 '18 at 18:03
|
show 1 more comment
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;
});
});
Thanks! Quick question: is.ref('genderCounters/' + userData.gender)
assuming that, in my database, I also have a child for genderCounters outside/under mystudents
child?
– gbm0102
Nov 20 '18 at 16:16
.ref('genderCounters/' + userData.gender)
would create a counter for a root nodegenderCounters/male
and a counter for a root nodegenderCounters/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 ofgenderCounters/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 thecounters/male
node.
– Renaud Tarnec
Nov 20 '18 at 18:03
|
show 1 more comment
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;
});
});
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;
});
});
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 mystudents
child?
– gbm0102
Nov 20 '18 at 16:16
.ref('genderCounters/' + userData.gender)
would create a counter for a root nodegenderCounters/male
and a counter for a root nodegenderCounters/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 ofgenderCounters/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 thecounters/male
node.
– Renaud Tarnec
Nov 20 '18 at 18:03
|
show 1 more comment
Thanks! Quick question: is.ref('genderCounters/' + userData.gender)
assuming that, in my database, I also have a child for genderCounters outside/under mystudents
child?
– gbm0102
Nov 20 '18 at 16:16
.ref('genderCounters/' + userData.gender)
would create a counter for a root nodegenderCounters/male
and a counter for a root nodegenderCounters/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 ofgenderCounters/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 thecounters/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
|
show 1 more comment
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
increase count while creating user
– Har Kal
Nov 20 '18 at 15:48