How to access snapshot of Firebase database within Firebase Function? - javascript

Every hour, I want my firebase function to look through my database, read a value, calculate a new value from this old value, and then update it in the database. I am having trouble accessing a snapshot of the data. Specificically,
exports.scheduledFunction = functions.pubsub.schedule('every 1 hour').onRun((context) => {
const ref = functions.database.ref('/users/test_user/commutes');
ref.once('value',function(snapshot) {
// do new calculation here
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
return null;
});
I am getting a : functions: TypeError: ref.once is not a function error.
How do I access a value from my firebase real time database and update it from a Firebase function?

You're trying to use the firebase-functions SDK to query the database. It can't do that. You will have to use the Firebase Admin SDK to make the query.
You will need to get started like this (not complete, but you should be able to see what you need to do). Import and initialize at the global scope:
const admin = require('firebase-admin')
admin.initializeApp()
Then in your function, use it. Be sure to work with promises correctly.
const ref = admin.database().ref('...')
return ref.once('value').then(snapshot => {
// work with the snapshot here, and return another promise
// that resolves after all your updates are complete
})

The firebase-functions is different from the client side. The ref() function according to the docs:
ref: function
ref(path: string): RefBuilder
Select Firebase Realtime Database Reference to listen to.
Path of the database to listen to.
Returns RefBuilder
The RefBuilder will contain the database triggers that you can call, onCreate(), onWrite(). To be able to use your database, then you need to use the admin sdk.
https://firebase.google.com/docs/reference/functions/providers_database_.refbuilder

Related

how can I toggle a boolean parameter in javascript?

I want to toggle a value called 'session' and then, update this value.
i've tried to do session=!session, but that didn't work.
session is a parameter inside a object, this object are displayed on my nosql database, i'm using the realtime database from firebase.
however session:true and session:false works
obs: English isn't my first lenguage, so sorry if I used wrong words.
Since you want to write a value to a path based on its existing value, you'll want to use a transaction.
Something like:
const userRef = ref(db, `/usuários/${fistKey}/session`);
runTransaction(userRef, (session) => {
if (session) {
return !session
}
return true; // 👈 default value
});

AngularFire collectionGroup always throws error not a valid function

I'm using Ionic 4 and have just integrated with AngularFire. Collections and documents work well, however I cannot get the collectionGroup function to work - it always gives an error that the function does not exist.
Relevant code is :
this.user = this.firestore.collection('profile').doc(tok.uid);
async StoreRecipe(recipe_name,meal) {
var ua = await this.read_foods_meal(meal+1)
console.log(meal);
ua.subscribe( foods => { console.log(foods);
foods.forEach(food => { this.user.collection('recipe').doc(recipe_name).collection('foods').add(food);} )
});
}
async read_recipes() {
var ua = await this.user.collectionGroup('recipe');
return(ua);
}
I have updated all modules with 'Fire' in the name to the latest version :
#angular/fire
#ionic-native/firebase-x
angularfire
firebase
firebase-admin
But the error still appears. Also, If I try to query the recipe collection using the .collection() function it just returns a null result .. even though there are documents under the 'recipe'collection
You user object is an instance of the firebase.firestore.DocumentReference class, and it does not have a collectionGroup method. Check the documetation here.
If you want to run a query across various collections, these should have the same name, and you can use the firebase.firestore().collectionGroup() method. You can find how to configure it in this link.
If you just want to get all the documents inside your recipe collection, you can make use of the CollectionReference.get() method (documentation).

Update another location onUpdate with firebase cloud functions [duplicate]

This question already has answers here:
Firebase DB - How to update particular value of child in Firebase Database
(3 answers)
Closed 4 years ago.
I am trying to keep some data consistent with firebase cloud functions. When data changes in the main list, I want all the data to change in the user's favourite list.
Currently, I am able to call the function and get a log of the correct data which is changing, but my query doesn't work. I am getting the following error:
TypeError: ref.update is not a function
at exports.itemUpdate.functions.database.ref.onUpdate
Here is my code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.itemUpdate = functions.database
.ref('/items/{itemId}')
.onUpdate((change, context) => {
const before = change.before.val(); // DataSnapshot after the change
const after = change.after.val(); // DataSnapshot after the change
console.log(after);
if (before.effects === after.effects) {
console.log('effects didnt change')
return null;
}
const ref = admin.database().ref('users')
.orderByChild('likedItems')
.equalTo(before.title);
console.log(ref);
return ref.update(after);
});
I'm not to sure where I am going wrong, I appreciate all the help and guidance to resolve this!
Cheers.
equalTo() returns a Query object. You're then trying to call update() on that object. Note that in the linked API docs, Query doesn't have an update() method. You can't simply "update" a Query that hasn't been performed. You're going to have to actually perform the query using once(), iterate the results form the snapshot in the returned promise, and perform further updates using the data you find.

Javascript Google Cloud Function try to get new added value in FirebaseDatabase

I followed the introduction of firebase to trigger if something has changed in my Database. I just want to log the new added values, but unfortunately it doesn't work. My Database structure looks like the following:
"Chat" : {
"-LGe_0ak8UOv9jFRukpZ" : {
"-LGe_3FgL6JkM-VQsg3K" : {
"Message" : "heiii na du",
"createdByUser" : "6dB5rWfSIwez3gO0N0ClBwFJKu53",
"ts" : 1530796459
},
"-LgeqadfFEA" : {
"Message" : "yo",
"createdByUser" : "asfdasdfasdfasdf",
"ts" : 123456677
}
},
So now the last item was added to my database and normally, I should receive a log with the new value, but the method was never started. I didn't receive any error as well. Here is my Method:
exports.makeUppercase = functions.database.ref('/Chat')
.onCreate((snapshot, context) => {
// Grab the current value of what was written to the Realtime
Database.
const original = snapshot.val();
console.log('ts', context.params.pushId, original);
const uppercase = original.toUpperCase();
// You must return a Promise when performing asynchronous tasks inside a
Functions such as
// writing to the Firebase Realtime Database.
// Setting an "uppercase" sibling in the Realtime Database returns a
Promise.
return snapshot.ref.parent.child('ts').set(uppercase);
});
The problem is that you have not correctly specified the realtime database path
You can use a wildcard to watch for changes within all 'chats' path, otherwise from your code, the function is watching for addition of actual key-value pair within your specified path whereas your intention is to watch for creation of a child
Example : functions.database.ref('/Chat/{pushId}').onCreate((snapshot, context) =>{
//Your execution
})
This tells cloud functions to watch creation of any object within the 'chat' path
You can further access the pushId variable through context.params.pushId
Happy coding

Why do I get this Cloud Firestore Function error?

I get this error in the Cloud Firestore Function log view.
I'm new to JavaScript and Firestore and could use some advice on this
TypeError: event.data.previous.data is not a function at
exports.onVisitorPres...
exports.onVisitorPresenceWrite = functions.database
.ref("/VISITORS_PRESENCE/{uid1}/{uid2}").onWrite((event) => {
// Get the data written or deleted on the Realtime Database
var eventStatus = event.data.val();
const previousData = event.data.previous.data();
// If the onWrite event is a delete event then use previousData
if(eventStatus == null){
eventStatus = previousData;
}
});
What I want to do is using the .onWrite((event) on a Firebase Realtime databas key and Firestore Function trigger when the key items get deleted and when new items are added.
I thought I could check the eventStatus == null and that is when data is deleted I simply use the previousData (before it got delete??)
The event variable is an instance of Event and therefore calling event.data will return a DeltaDocumentSnapshot for Firestore and a DeltaSnapshot for the Realtime Database.
With a these delta snapshots, you can obtain the previous value with previous which will return another DeltaDocumentSnapshot or DeltaSnapshot containing the previous state from before the write event was triggered.
In your example, you're using a Firebase Realtime Database trigger, which means event.data.previous will return a DeltaSnapshot, which does not support data(), but instead supports val().
In this case, as you've done with var eventStatus = event.data.val();, you need to call val() on previous:
const previousData = event.data.previous.val();
If instead you are trying to use a Firestore trigger, you need to change this:
functions.database.ref("[...]")
To this:
functions.firestore.document("[...]")
And then you can use event.data.previous.data().

Categories