how to write function for a specific document in firestore? - node.js

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

Related

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 wait two OnCreate Firebase Functions finished

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
});

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

Realtime Database ref change can' t detect

I created a Db. Name Tomris
Below that is a 'Cumle': "Sentence". Whatever I do here does not happen.
https://i.stack.imgur.com/EEKAk.png
What I want is Trigger work when the sentence changes. But I couldn't.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
exports.DBTrigger = functions.database.ref('tomris-d96a7/Cumle')
.onWrite( (change, context) => {
const afterData = change.after.data();
console.log(afterData);
console.log ("onur");
});
You included the name of your database in the Cloud Functions trigger, which is not needed and in fact means your Function is now looking at a non-existing path.
To trigger on the correct path, only include that path in the Function definition:
exports.DBTrigger = functions.database.ref('Cumle')
...

Saving to two different Firestore databases with dialogflow

I'm making an actions on google project that will require adding data to two different Cloud Firestore. For some reason when I trigger the intent, it will only save to the original Cloud Firestore, but not the new one.
For simplicity, I'm going to refer to the original Cloud Firestore as "DB1" and the new one/ second one as "DB2"
Here's what I had tried:
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const admin = require('firebase-admin');
const {google} = require('googleapis');
const {
<Basically All of the libraries / AOG functions>
} = require('actions-on-google');
const defaultAppConfig = {"<FIREBASE CREDENTIALS FOR DB1 >"}
const OtherAppConfig = {"<FIREBASE CREDENTIALS FOR DB2>"}
const defaultApp = admin.initializeApp(defaultAppConfig); // DB1
const otherApp = admin.initializeApp(OtherappConfig, 'Other'); // DB2
const db = admin.firestore(functions.config(defaultApp).firebase); //DB1
const ab = admin.firestore(functions.config(otherApp).firebase); // DB2
const app = dialogflow({
debug: true,
clientId: '<DIALOGFLOW CREDENTIALS>'
});
app.intent('DB2 Write', (conv) =>{
conv.ask('Okay I made the write to DB2');
var data = {
name: 'This is a Test write'
};
var setDoc = ab.collection('Test').doc('Write').set(data);
});
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
Sorry if some parts are unnecessary, I wanted to include as much information as I could (I might be missing something that someone else sees).
To sum up what I thought would happen, I thought when I triggered the intent 'DB2 Write' that it would write 'This is a Test Write' to DB2, however it just keeps writing the message/data to DB1.
How do I get this working so it will write to my second Cloud Firestore or "DB2" when this intent is triggered?
Thanks for the help!
Note: If it makes a difference, I'm using the dialogflow inline editor for this code.
____________________________________________________________________________
Update: Here is what I have tried/ updated and it still writes to DB1
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
const otherAdmin = require('firebase-admin');
otherAdmin.initializeApp({
credential: otherAdmin.credential.cert(OtherAppConfig)
},'Other');
const ab = otherAdmin.firestore();
and as well:
admin.initializeApp(defaultAppConfig);
var otherApp = admin.initializeApp(OtherAppConfig, 'other');
console.log(admin.app().name); // '[DEFAULT]'
console.log(otherApp.name); // 'other'
// Use the shorthand notation to retrieve the default app's services
var db = admin.firestore(functions.config().firebase);
// Use the otherApp variable to retrieve the other app's services
var ab = otherApp.firestore(functions.config().firebase);
I'd like to note, the credentials I'm using for "OtherAppConfig" and "defaultAppConfig" were taken from the Firebase private key. ie: firebase console > project overview > service accounts > generate private key. Could this be the problem?
I think the problem is thus:
A Dialogflow project and a Firebase project are the same under the hood. This cool, as your Firebase Functions will know intuitively connect with Dialogflow and your database without a lot of manual configuration.
However, if you have two databases from different Cloud Projects, you will need to do some additional configurations to connect securely. I'm not sure what your AppConfigs contain, but they may not be sufficiently setup. As such, the Firebase setup may be pulling the default (current project) app and database when you're grabbing the functions config.
You may want to, for your second project, download the service key. Then you can load it as a file or directly as JSON in your startup routine.
This snippet below should work the way you want.
// Setup 1st db, this project's db
const admin = require('firebase-admin');
admin.initializeApp(); // Initialize with default params as we get it by default
const db = admin.firestore();
// Setup 2nd db
const otherAdmin = require('firebase-admin'); // We can import twice
const myOtherServiceKey = { ... }
otherAdmin.initializeApp({
credential: otherAdmin.credential.cert(myOtherServiceKey)
});
const ab = otherAdmin.firestore(); // This should be the DB of our second project

Resources