我想用node.js创建一个函数,但是我被卡在了某个地方。
我要做什么的解释:
首先,当新文档添加到路径配置文件/ {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数据库说明。
个人资料| profileDocument |帖子和关注者|追随者收集文件和帖子收集文件
我有一个名为profile的父集合,它包含文档,因为这些文档的任何集合都包含一个我要访问的名为tokenID的字段,但是我不会仅对关注者(追随该Profile的用户)的所有用户执行此操作创建了一个新的集合,称为关注者,其中包含所有关注者ID,我要获取每个关注者ID,并为每个ID将tokenID推送到令牌列表中。
最佳答案
如果我正确理解您的问题,则应该执行以下操作。请参阅下面的说明。
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/');
不会声明DocumentReference
,因为您的路径由3个元素(即Collection / Doc / Collection)组成。另请注意,在Cloud Function中,您需要使用Admin SDK来读取其他Firestore文档/集合:因此,您需要执行admin.firestore()
(var x = firestore.doc(...)
将不起作用)。其次,不能仅通过执行
profileID
来获取{profileID}
的值:您需要使用context
对象,如下所示const profileID = context.params.profileID;
。因此,应用以上内容,我们声明
CollectionReference
followersCollecRef
并调用get()
方法。然后,我们用querySnapshot.forEach()
遍历此Collection的所有文档,以填充tokens
数组。其余部分很简单,并且与您的代码一致。
最后,请注意,从v1.0开始,您应该使用
admin.initializeApp();
轻松初始化Cloud Functions,请参见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;
});
});