How to wait two OnCreate Firebase Functions finished - node.js

I want to wait until the second OnCreate its finished for trigger a notification. The thing is that the second OnCreate depends on the first OnCreate document.
Because I don't know the document id at "comida" until it is created in "Proveedores". Here is my database:
I want to trigger when a new document at "Pedidos" from that document id that is in "comida" is created.
This is what I have try:
export const newProveedorAdd = functions.firestore
.document("Proveedores/{proveedorID}")
.onCreate(async (snapshot) => {
const idProveedor = snapshot.id;
const infoProveedor = snapshot.data();
if (infoProveedor) {
const RUC = infoProveedor.RUC;
console.log("Proveedor nuevo id: " +idProveedor + " RUC: " + RUC);
console.log("Ruta doc: "+"comida/"+idProveedor+"{proveedoID}/Pedidos/{pedidoID}");
await functions.firestore
.document("comida/"+idProveedor+"/Pedidos/{pedidoID}")
.onCreate((snapshot) => {
const numPedido = snapshot.id;
console.log("ENTRO 2 " + numPedido);
return Promise;
});
}
});
This is also the console from Firebase Functions. It seems that is not waiting for the second OnCreate to finish

You are using a Cloud Firestore onCreate() trigger within a triggered Cloud Function code which will not work. Because the Cloud Firestore events are intended to be used for Cloud Functions and it will only listen to an exported object of functions.firestore. Also one Cloud Function can listen to one trigger. So, for multiple triggers one has to use multiple Cloud Functions.
In your case you have a Proveedores collection and a comida collection. You want to trigger a Cloud Function when a document inside the Proveedores collection is created. Now again you also want to send notifications when a document is created inside the Pedidos subcollection which is inside the document having the document id same as that of the document in the Proveedores collection which was created earlier.
To implement the above I would suggest you use two Cloud Functions.
Function-1 is triggered when a document is created inside the Proveedores collection. Inside this Function you can create an empty document inside Pedidos subcollection, which is inside a document, having the document id same as the document created in the Proveedores collection, within the comida collection. When the document is created it will trigger Function-2 as it is created to listen to the onCreate() event on comida/{comidaID}/Pedidos/{pedidosID}, where the logic to send notification can be implemented.
Function : 1
const admin = require("firebase-admin");
const functions = require("firebase-functions");
admin.initializeApp();
const db=admin.firestore();
exports.newFunction = functions.firestore.
document("Proveedores/{proveedorID}").onCreate((snapshot)=>{
const idProveedor = snapshot.id;
const infoProveedor = snapshot.data();
if (infoProveedor) {
const name = infoProveedor.name;
console.log("Proveedor nuevo id: " +idProveedor + " Name: " + name);
db.collection("comida").doc(idProveedor).
collection("Pedidos").doc().set({});
}
});
Function : 2
const admin = require("firebase-admin");
const functions = require("firebase-functions");
admin.initializeApp();
// const db=admin.firestore();
exports.newFunction = functions.firestore.
document("comida/{comidaID}/Pedidos/{pedidosID}").onCreate((snapshot)=>{
const idPedidos = snapshot.id;
console.log("The document has been created with document Id: "+idPedidos);
// implement logic to send notifications here
});

Related

Listen for changes in a Firestore collection

Firestore has a specific documentation for listening documents changes, like add, modify or remove (https://firebase.google.com/docs/functions/firestore-events).
For example, I can use an export function like the following to listen for a new document.
const functions = require('firebase-functions');
exports.myFunction = functions.firestore
.document('my-collection/{docId}')
.onCreate((change, context) => { /* ... */ });
Currently I'm building a Cloud Function that inserts multiple documents by means of a batch writing mechanism like the following.
const colRef = firestore.collection(collectionName)
const batch = firestore.batch();
items.forEach(item => {
let docId = hashCode(item.title);
let docRef = colRef.doc(`${docId}`);
batch.set(docRef, {
index: `${item.index}`,
description: `${item.description}`,
title: `${item.title}`
});
});
return await batch.commit();
What I would like to achieve is the following: when I insert multiple documents into a collection, I need to send a push notification to my mobile client in order to let users know that new documents are available.
onCreate, onUpdate, onDelete or onWrite operate on a single document change and not in the entire collection.
Is there a way to listen when into a collection are added a bunch of elements?
Thanks,
Lorenzo
Cloud Firestore events trigger on document changes and each new document will trigger a Cloud Function. Instead you can use a Callable Cloud Function that adds runs batched write and also send the notification. For example:
exports.sendNotification = functions.https.onCall((data, context) => {
const { docs } = data;
// TODO:
// 1. Run Batched Write
// 2. Send notification to user
});
This will invoke only 1 Cloud Function for all documents instead of a function for each document.

Automatically generating cloud functions when group created

What is the best approach for my case? A user creates a messaging group in my app. Then the group will get its own auto id.
Now I want to use cloud func from firebase to check for new messages and to do a push notification.
The code below checks if a group is created and send the push notification. But this only works when I know the generated auto id and post it manually in the code below. How can I solve this issue? Should my App create for each group its own cloud function? Would this not be too much? Or can I use somehow a wildcard?
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.Push = functions.database.ref('/placeID/theGeneratedIdComesHere/{messageID}/')
.onCreate((snapshot, context) => {
var nameUser = String(snapshot.val().userName)
var textUser = String(snapshot.val().userComment)
var topic = 'weather';
const payload = {
notification: {
title: nameUser,
body: textUser,
badge: '1',
sound: 'default'
}
};
admin.messaging().sendToTopic(topic,payload);
})
You can make the group ID a parameter on your Cloud Function declaration:
exports.Push = functions.database.ref('/placeID/{groupID}/{messageID}/')
Then you can access that group ID in your functions code with:
const groupID = context.params.groupID;
And then you can use that value in your code to make it to what this specific group needs.

how to write function for a specific document in firestore?

below is the function, i have used from youtube .
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.androidPushNotification =
functions.firestore.document('MyMoneyNotifications/{MyPercentageMoney}').onCreate(
(snapshot, context)=>
{
admin.messaging().sendToTopic(
"new_user_forums",
{
notification:{
title:snapshot.data().title,
body: snapshot.data().body
}
});});
it is working fine.
but i want to check for below structure.
Notifications(collection)
->UserId(document)
->MyNotification(collection)
->notify1
->notify2
now, i want to check for a specific user if he had any new notifications. how to check for the collection "MyNotification" in firebase functions
If you are trying to listen to sub-collections then you can set the path to:
exports.androidPushNotification =
functions.firestore.document('Notifications/{userId}/MyNotification/{notificationId}')
You can read more about this in the documentation

Firebase functions multi child change

hi firebase functions I want to change multiple children, but cannot change all children under user id. can you help me with this topic
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var database = admin.database();
exports.newNodeDetected = functions.database.ref('system/{userId}/value')
.onWrite((Change) =>{
var oldDeger = Change.before.val();
var newDeger = Change.after.val();
if (newDeger === '0'){
database.ref(`system/${userId}/value`).set('1');
}
})
enter image description here
You can update multiple children in several ways using standard object manipulation and direct writes as demonstrated in your question.
You may be interested in using update rather than set when updating multiple fields.
You will also notice I added a Context field which allows you to access information such as the userID from the reference path and other information: Source
exports.newNodeDetected = functions.database.ref('system/{userId}/value')
.onWrite((Change, Context) =>{
var oldDeger = Change.before.val();
var newDeger = Change.after.val();
if (newDeger === '0'){
database.ref(`system/${Context.params.userId}/value`).set('1');
database.ref(`system/${Context.params.userId}/otherField`).update({another:field});
}
})
Resource: Medium Article: Realtime Set Vs Update

How to get inner child in cloud function for Firebase?

Here is my database and I want to trigger onWrite event on children of PUBLISHED_CONTENT_LIKES. When I add another userId under publishedContentId1, I can identify contentId as publishedContentId1 in my cloud function using event.params.pushId.
exports.handleLikeEvent = functions.database.ref('/USER_MANAGEMENT/PUBLISHED_CONTENT_LIKES/{pushId}')
.onWrite(event => {
// Grab the current value of what was written to the Realtime Database.
//const userId = event.data.child(publishedContentId);
//const test = event.params.val();
const publishedContentId = event.params.pushId;
var result = {"publishedContentId" : "saw"}
// 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 event.data.ref.parent.parent.child('PUBLISHED_CONTENTS/'+publishedContentId).set(result);
});
However I want to get newly added userId as well. How to get that userId using above event?
You can get the data that is being written under event.data. To determine the new user ID:
event.data.val().userID
I recommend watching the latest Firecast on writing Database functions as it covers precisely this topic.

Resources