【问题标题】:How to push notifications in firebase node.js cloud functions?如何在 firebase node.js 云功能中推送通知?
【发布时间】:2020-04-01 08:25:23
【问题描述】:

我想用 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 的字段并且我想访问,但我不会仅为关注者(关注该配置文件的用户)对所有用户执行此操作) 所以我创建了一个名为 follower 的新集合,它包含所有关注者 ID,我想获取每个 followerID 并为每个 id 推送 tokenID 到令牌列表。

【问题讨论】:

    标签: node.js firebase push-notification google-cloud-firestore google-cloud-functions


    【解决方案1】:

    如果我正确理解您的问题,您应该执行以下操作。请参阅下面的说明。

    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() 循环这个集合的所有文档以填充tokens 数组。

    剩下的部分很简单,符合你的代码。


    最后,请注意,从 v1.0 开始,您应该使用 admin.initializeApp(); 简单地初始化 Cloud Functions,请参阅 https://firebase.google.com/docs/functions/beta-v1-diff#new_initialization_syntax_for_firebase-admin


    跟随你的 cmets 更新

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

    【讨论】:

    • 我很乐意为您提供帮助,但您需要非常清楚地解释不同文档的确切参考资料。在您的评论中,您谈到了“收藏”领域。很难确切地理解什么是什么。请更新您的问题,明确说明显示不同文档的确切路径。
    • @thecoder 查看更新。如果答案回答了您的问题,请接受并投票。见stackoverflow.com/help/someone-answers。谢谢。
    • 是的,我的回答中有一个错字:我大约在 15 分钟前修改了它。请在答案中使用新代码。
    • 在我的回答中,在底部。我已经按照我说的修改了它,所以再次复制它。你可以在这里看到修改stackoverflow.com/posts/59228683/revisions
    • 很抱歉浪费了您的时间,谢谢!成功了!
    猜你喜欢
    • 1970-01-01
    • 2019-12-18
    • 2018-06-01
    • 2020-09-09
    • 2021-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-23
    相关资源
    最近更新 更多