Firebase database on push get id - javascript

I am trying to imitate an insertion trigger on Firebase using the onWrite method. The insertion is done via POST requests since I am testing it (easiest way I found to check database triggers). The trigger includes writing the Firebase generated ID inside the inserted data as a new property.
My cloud function is this:
exports.onNewSeries = functions.database.ref('/series').onWrite(event => {
"use strict";
console.log(event.data.key);
console.log(event.data.current.key);
console.log(event.data.current);
});
Both first logs contain the same key (series), which actually is the key of the parent node where the new data is appended, instead of the new data key (in the quirky form of -adfaa123sdfasdf). The last log prints a Firebase structure containing the new data as well as the generated key in a _data property, however it is not accessible.
While this can be done manually after a request, I have not seen it automated in a database trigger way.

To get the generated key, make the function trigger on a specific child:
exports.onNewSeries = functions.database.ref('/series/{id}').onWrite(event => {
console.log(event.params.id);
});
Also see the Firebase documentation on handling database events.

Related

How can I access the child of a unique key in Firebase?

I am trying to access the child value of a unique key value (that had been "pushed") within Firebase. Currently, my database looks like this: I want to access the value of "emailOfUser"
I am very new to Firebase so I am not familiar with the functions. Currently, this is my method of obtaining other values for a different section of the database:
Thank you so much for any feedback!
I've tried different methods to accessing this data within the Firebase, but I cannot get it to work/the methods I were using were outdated. I also tried to "update" the Firebase instead of "pushing" the values to prevent a unique key from generating, but it simply overwrote my current data rather than appending something new.
If you want to load all the users who voted and print their emails, you can do that with:
get(child(dbref, 'usersWhoVoted')).then((snapshot) => {
snapshot.forEach((childSnapshot) => {
console.log(childSnapshot.key, childSnapshot.val().emailOfUser);
});
})
Note that your current structure allows a user to vote multiple times. If you want to only allow them to vote once, use some identifier of the user as the key in your database structure:
userVotes: {
"uniqueIdOfUser1": "valueTheyVotedOn",
"uniqueIdOfUser1": "valueTheyVotedOn",
...
}
Now each user can by definition only vote once, If they vote again (assuming your security rules allow that), their new vote will simply replace the existing vote.

How to only read changes in firebase realtime database

I have a database collection with readings, each new reading needs to be checked if it's out of the ordinary, if it is, there needs to be an alert sent.
So i'm using db.ref('collection').on('child_added', (child => { check(child); });
The problem with the .on function is that when the listener is added, all previous data is also read.
So how do i read a collection that only reads the changes in the database, also when the listener is first added? Or if that doesn't work, how do I differentiate the already added data with the new data?
The Firebase database synchronizes the state of whatever query or reference you attach your listener to. There is no option to only get new nodes built into the API.
If you want only new nodes, you will have to:
Ensure each node has an associated timestamp or order. If you're using Firebase's built-in push() keys, those might already serve that function.
Know what "new" means to the client, for example by either keeping the last timestamp or push key that it saw.
And then use a query to only request nodes after the stores timestamp/key.
So for example, if you only want to read nodes that are created after the moment you attach the listener, you could do something like this:
let now = db.ref('collection').push().key; // determine current key
db.ref('collection').orderByKey().startAt(now).on('child_added', ...)

How to compare value and delete from firebase realtime database?

I am using Firebase realtime database in Android app, and have data like this:
How can I access that data from javascript.
I just wanna code function to get value of every endTime and compare with current time and if endTime <= Current Time then delete values yellow marked on anther image.
Events is fixed value.
Indjija, Vojvodina and -KsB2mVkpgQe_fRyFFH4 are auto generated so it's possible to have more values like that two.
I know how to solve that in android studio with Java code but I'm interesting about implementing server functions.
The answer to this question is buried deep within Firebase Database Reference.
forEach() is used to get to the child without knowing the child's exact path.
var leadsRef = database.ref('leads');
leadsRef.on('value', function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var childData = childSnapshot.val();
});
});
Now childSnapshot will contain the required data, the same thing can also be accessed using child_added.
leadsRef.on('child_added', function(snapshot) {
//Do something with the data
});
The only difference is that in case of forEach(), it will loop through from the start so if any new data will be added, it will also load the previous data but in case of child_added, the listener is only on new child and not the previous existing childs.
Useful Link:
Firebase Read and Write Web
Hope it helps.

Test if value is the same of Firebase database

I have a realtime database in a Firebase project, with a registered value.
In a minigame, the device reads a QR-Code and store the information. So I want to send the value to Firebase, to the server test if value is the same of the database, and return just "true" or "false".
I can do this, but I get the value to the device and I perform the test in the client. My goal is just send the value and the server will perform the test.
I'm a newbie in Firebase, and I'm not sure if I can do this.
Assuming you have already linked Firebase to your app, you first need to make two references to your database:
var database = firebase.database(); //This links to your database
and
var nodeRef = firebase.database().ref("value/").child("IF APPLICABLE"); //This references to the node you want to compare.
Notice .child(). If the node you want is nested inside another node, you have to use .child("NODE HERE") to reference it.
Next to read the value, you would use:
nodeRef.on('value', function(snapshot) {
nodeValue = snapshot.val();
if (nodeValue == comparisonValue) {
//Do something
});
This calls on your reference and gets its value in your database. Then, within the if statement, you can execute the code that you want. You just have to make sure that they use the same word before the ".on".
Please ask if you need any more clarification!

How to prevent 'value' event on the client that issued set?

A Firebase client calling set() will cause all connected clients to have value triggered - including - the original client that issued the set().
In my case (and I think in most cases), there is no reason for the client that issued the set() to respond to the value event produced by its own call. Obviously its model is correct and there's no need to change it (which may be an expensive operation).
Is there any way for the client to not-receive/prevent/ignore the value event triggered by its own set() call ? I considered using off/on around set() but that can make the client miss value events that came at the same time but were not triggered by it.
Am I missing something obvious ?
Most applications treat the Firebase data itself as their model. So when there's an update, they call ref.set() (or another mutator function) and then the update flows back into their app through an on() event. React/Flux aficionados know this as a unidirectional data-flow, other might know it as Command Query Responsibility Segregation.
But there indeed cases where the model has already been updated and thus you want to ignore the event from Firebase if you're the one who triggered it.
There is no API for not receiving theses self-triggered events. Instead you'll have to "remember" the data that you sent to Firebase and filter it out in your on() handler.
The Android drawing sample from Firebase keeps a list of segments that it sends to Firebase and then ignores those segments in its onChildAdded handler. It uses push ids to identify the line segments and those are generated client-side, so it can use those to track identify the segments.
A JavaScript sample of this:
var pendingChildIds = []; // Push ids of nodes we've sent to the server, but haven't received in `on()` yet
// this code is in your UI event handler, or whatever triggers the needs to update your Firebase data
var newChild = ref.push();
pendingChildIds.push(newChild.key());
newChild.set(
{ property1: 'value1', property2: 3.14 },
function(error) {
// the write operation has completed, remove the child id from the list of pending writes
pendingChildIds.splice(pendingChildIds.indexOf(newChild.key());
}
);
// this is the event handler, using child_added in this case
ref.on('child_added', function(snapshot) {
if (!pendingChildIds.contains(snapshot.key())) {
// this is a child that we DIDN'T generate
}
});
I ended up adding a client ID to the model, something like:
var clientId=(Math.random()*10000000000000000).toFixed(0);
function set(data) {
ref.set(JSON.stringify({ clientId: clientId, data: data }));
}
ref.on('value', function(snapshot) {
var json=JSON.parse(snapshot.val());
if (!json || json.clientId===clientId) return;
var data=json.data;
// update model with data
});

Categories