node.js - 如何在 firebase node.js 云功能中推送通知?
问题描述
我想用 node.js 创建一个函数,但我陷入了困境。
我想做的解释:
首先,该函数将在路径 profile/{profileID}/posts/{newDocument} 中添加新文档时触发
该功能将向以下所有用户发送通知。问题来了。
我在配置文件集合中有另一个集合,它是关注者,包含字段 followerID 的文档。
我想使用这个 followerID 并将其用作文档 ID 来访问我已添加到配置文件文档中的 tokenID 字段。
像这样:
..(profile/followerID).get(); 然后访问 tokenID 字段的字段值。
我当前的代码:- Index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.fcmTester = functions.firestore.document('profile/{profileID}/posts/{postID}').onCreate((snapshot, context) => {
const notificationMessageData = snapshot.data();
var x = firestore.doc('profile/{profileID}/followers/');
var follower;
x.get().then(snapshot => {
follower = snapshot.followerID;
});
return admin.firestore().collection('profile').get()
.then(snapshot => {
var tokens = [];
if (snapshot.empty) {
console.log('No Devices');
throw new Error('No Devices');
} else {
for (var token of snapshot.docs) {
tokens.push(token.data().tokenID);
}
var payload = {
"notification": {
"title": notificationMessageData.title,
"body": notificationMessageData.title,
"sound": "default"
},
"data": {
"sendername": notificationMessageData.title,
"message": notificationMessageData.title
}
}
return admin.messaging().sendToDevice(tokens, payload)
}
})
.catch((err) => {
console.log(err);
return null;
})
});
我的 Firestore 数据库解释。
简介 | profile文件| 帖子和关注者 | 追随者收集文件和帖子收集文件
我有一个名为 profile 的父集合,它包含文档作为任何集合,这些文档包含一个名为 tokenID 的字段并且我想访问,但我不会只为关注者(关注该配置文件的用户)对所有用户执行此操作,所以我'已经创建了一个名为追随者的新集合,它包含所有追随者 ID,我想获取每个追随者 ID,并为每个 ID 推送令牌 ID 到令牌列表。
解决方案
如果我正确理解您的问题,您应该执行以下操作。请参阅下面的说明。
exports.fcmTester = functions.firestore.document('profile/{profileID}/posts/{postID}').onCreate((snapshot, context) => {
const notificationMessageData = snapshot.data();
const profileID = context.params.profileID;
// var x = firestore.doc('profile/{profileID}/followers/'); //This does not point to a document since your path is composed of 3 elements
var followersCollecRef = admin.firestore().collection('profile/' + profileID + '/followers/');
//You could also use Template literals `profile/${profileID}/followers/`
return followersCollecRef.get()
.then(querySnapshot => {
var tokens = [];
querySnapshot.forEach(doc => {
// doc.data() is never undefined for query doc snapshots
tokens.push(doc.data().tokenID);
});
var payload = {
"notification": {
"title": notificationMessageData.title,
"body": notificationMessageData.title,
"sound": "default"
},
"data": {
"sendername": notificationMessageData.title,
"message": notificationMessageData.title
}
}
return admin.messaging().sendToDevice(tokens, payload)
});
首先,var x = firestore.doc('profile/{profileID}/followers/');
您不要声明 a DocumentReference
,因为您的路径由 3 个元素组成(即 Collection/Doc/Collection)。另请注意,在 Cloud Function 中,您需要使用Admin SDK才能读取其他 Firestore 文档/集合:所以您需要这样做admin.firestore()
(var x = firestore.doc(...)
将不起作用)。
其次,你不能profileID
仅仅通过做得到价值{profileID}
:你需要使用context
对象,如下const profileID = context.params.profileID;
。
因此,应用上述内容,我们声明 a并调用该方法。然后我们遍历这个集合的所有文档来填充数组。CollectionReference
followersCollecRef
get()
querySnapshot.forEach()
tokens
剩下的部分很简单,并且符合您的代码。
最后,请注意,从 v1.0 开始,您应该使用 简单地初始化您的 Cloud Functions admin.initializeApp();
,请参阅https://firebase.google.com/docs/functions/beta-v1-diff#new_initialization_syntax_for_firebase-admin
根据您的评论更新
以下 Cloud Function 代码将查找每个关注者的 Profile 文档,并使用tokenID
该文档中的字段值。
(请注意,您也可以将其tokenID
直接存储在 Follower 文档中。您会复制数据,但这在 NoSQL 世界中很常见。)
exports.fcmTester = functions.firestore.document('profile/{profileID}/posts/{postID}').onCreate((snapshot, context) => {
const notificationMessageData = snapshot.data();
const profileID = context.params.profileID;
// var x = firestore.doc('profile/{profileID}/followers/'); //This does not point to a document but to a collectrion since your path is composed of 3 elements
const followersCollecRef = admin.firestore().collection('profile/' + profileID + '/followers/');
//You could also use Template literals `profile/${profileID}/followers/`
return followersCollecRef.get()
.then(querySnapshot => {
//For each Follower document we need to query it's corresponding Profile document. We will use Promise.all()
const promises = [];
querySnapshot.forEach(doc => {
const followerDocID = doc.id;
promises.push(admin.firestore().doc(`profile/${followerDocID}`).get()); //We use the id property of the DocumentSnapshot to build a DocumentReference and we call get() on it.
});
return Promise.all(promises);
})
.then(results => {
//results is an array of DocumentSnapshots
//We will iterate over this array to get the values of tokenID
const tokens = [];
results.forEach(doc => {
if (doc.exists) {
tokens.push(doc.data().tokenID);
} else {
//It's up to you to decide what you want to to do in case a Follower doc doesn't have a corresponding Profile doc
//Ignore it or throw an error
}
});
const payload = {
"notification": {
"title": notificationMessageData.title,
"body": notificationMessageData.title,
"sound": "default"
},
"data": {
"sendername": notificationMessageData.title,
"message": notificationMessageData.title
}
}
return admin.messaging().sendToDevice(tokens, payload)
})
.catch((err) => {
console.log(err);
return null;
});
});
推荐阅读
- testing - 如何在 Cypress 的 E2E 测试中登录 Auth0?
- python - Keras 打开图像并使用它们创建批处理
- r - 嵌套循环遍历 R 中的不同列表
- java - Hibernate 中枚举和 json 类型的问题
- bing - Bing 实体搜索在美国以外不可用
- python - Docker build pytest:无法建立新连接:[Errno 111] Connection denied
- reactjs - 选择字段未填充 从 Redux 表单中的下拉数组中选择值
- python - 纪元纳秒到正常时间
- speech-recognition - 有什么方法可以提高 Pocketsphinx 在语音识别方面的准确性吗?
- javascript - Metamask 仅在页面刷新后注入 web3