Reputation: 3724
Most of the examples i have seen explain how to listen to a document with the uid of a user.I am trying to listen to just the general parent collection
exports.sendNotifications = functions.firestore.document('Notifications').onCreate(async (snapshot) => {
// Notification details.
const payload = {
notification: {
title: 'Hello',
body: 'Hello again',
click_action: `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com`,
}
};
// Get the list of device tokens.
const allTokens = await admin.firestore().collection('fcmTokens').get();
const tokens = [];
allTokens.forEach((tokenDoc) => {
tokens.push(tokenDoc.id);
});
if (tokens.length > 0) {
// Send notifications to all tokens.
const response = await admin.messaging().sendToDevice(tokens, payload);
}
});
This cloud function brings functions: failed to create function sendNotifications
HTTP Error: 400, The request has errors
. The error I am guessing is because the firestore collection is not being referenced properly. It is the root collection. How can I reference it better
Upvotes: 1
Views: 1501
Reputation: 83093
There are several points that you should modify in your Cloud Function:
1/ You should trigger it when a Document is created, as follows. See https://firebase.google.com/docs/functions/firestore-events?authuser=0#wildcards-parameters.
exports.sendNotifications = functions.firestore.document('Notifications/{notifId}')
.onCreate(async (snap, context) => {
const newValue = snap.data();
// perform desired operations ...
// You may not need the notifId value but you have to keep the wildcard in the document path
});
2/ Also, note how onCreate()
has a data
and a context
parameters. See https://firebase.google.com/docs/functions/firestore-events?authuser=0#trigger_a_function_when_a_new_document_is_created and https://firebase.google.com/docs/functions/beta-v1-diff?authuser=0#cloud-firestore for more details.
3/ Finally, you should return the promise returned by the admin.messaging()
asynchronous task as well as returning a value in case tokens.length = 0
. These two actions ensure you indicate to the platform that the work of the Cloud Function is finished. (I would suggest you watch the 3 videos about "JavaScript Promises" from the Firebase video series: https://firebase.google.com/docs/functions/video-series/)
So, at the end your code would look as follows. (Note that I've not tested it, so I cannot 100% guarantee that it will solve your "HTTP Error: 400, The request has errors" problem...)
exports.sendNotifications = functions.firestore.document('Notifications/{notifId}')
.onCreate(async (snap, context) => {
// Notification details.
const payload = {
notification: {
title: 'Hello',
body: 'Hello again',
click_action: `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com`,
}
};
// Get the list of device tokens.
const allTokens = await admin.firestore().collection('fcmTokens').get();
const tokens = [];
allTokens.forEach((tokenDoc) => {
tokens.push(tokenDoc.id);
});
if (tokens.length > 0) {
// Send notifications to all tokens.
return await admin.messaging().sendToDevice(tokens, payload);
} else {
return null;
}
});
Upvotes: 3