【问题标题】:How to scale push notifications in Firebase Cloud functions for this use case?如何为此用例扩展 Firebase Cloud 功能中的推送通知?
【发布时间】:2018-09-03 01:35:19
【问题描述】:

在我的应用中,当用户创建新帖子时,我会向该用户的关注者发送推送通知。正如您在下面的代码中看到的,我需要从每个关注者的个人资料中查询一些额外的设置,以获取他们的推送令牌并检查一些额外的通知设置。如果用户拥有大量关注者(即 1000),我担心每个用户的个人资料的查询可能会成为瓶颈。

解决这个问题的最佳方法是什么?

// The cloud function to trigger when a post is created
exports.newPost = functions.database.ref('/posts/{postId}').onCreate(event => {

    const postId = event.params.postId;
    const post = event.data.val();
    const userId = post.author;

    let tokens = [];
    let promises = [];

    return admin.database().ref(`/followers/${userId}`).once('value', (followers) => {
        followers.forEach((f) => {
            let follower = f.key;
            promises.push(
                admin.database().ref(`users/${follower}`).once('value')
            );
        });
    })
    .then(() => {
        return Promise.all(promises).then((users) => {
            users.forEach((user) => {
                const userDetails = user.val();
                if (userDetails.post_notifications) {
                    if(userDetails.push_id != null) {
                        tokens.push(userDetails.push_id);
                    }
                }
            })
        })
    })
    .then(() => {
        if (tokens.length > 0) {
            const payload = {
                notification: {
                    title: 'New Post!',
                    body: 'A new post has been created'
                }
            };
            // Send notifications to all tokens.
            return admin.messaging().sendToDevice(tokens, payload);
        }
    });
})

编辑:

我们考虑过使用主题。但是我们不确定我们如何仍然可以让我们的自定义通知设置与主题一起使用。这是我们的困境。

我们有多个可以创建通知的操作,并且我们为应用中的每种通知提供单独的开关,以便用户可以选择他们想要关闭的通知类型。

假设用户 A 关注用户 B。我们可以为用户 A 订阅“用户 B 的主题”,因此每当用户 B 执行向他/她的关注者发送通知的操作时,我都可以向订阅的用户发送通知“用户 B 主题”。

因为我们在应用中有多个通知开关,并且当用户 A 更改他/她的设置,他们不希望收到新帖子的通知但仍希望收到他/她关注的用户的其他类型的通知时,我们无法弄清楚在这种情况下我们如何使用主题。

【问题讨论】:

  • 你不能使用主题吗?
  • @PeterHaddad 我已经编辑了问题并解释了为什么我们没有使用主题。也许您可以根据我写的关于使用主题的内容进行更多详细说明。

标签: javascript firebase firebase-cloud-messaging google-cloud-functions


【解决方案1】:

您可以为此使用主题,而不是使用令牌。因此,假设用户开始关注某人,然后他将注册到该主题。

假设他跟着一个叫“彼得”的人,那么你可以执行这个:

FirebaseMessaging.getInstance().subscribeToTopic("Peter");

如果你有这个数据库:

posts
  postid
     postdetails: detailshere
     author: Peter

然后使用onCreate():

exports.newPost = functions.database.ref('/posts/{postId}').onCreate(event => {
const postId = event.params.postId;
const post = event.data.val();
const authorname = post.author;
const details=post.postdetails;

const payload = {
 data: {
    title:userId,
    body: details,
    sound: "default"
     },
  };

 const options = {
    priority: "high",
     timeToLive: 60 * 60 * 24
    };

return admin.messaging().sendToTopic(authorname, payload, options);
 });

你可以使用这个,每次作者创建一个新帖子时,onCreate() 被触发,然后你可以在通知中添加帖子的详细信息和作者姓名(如果需要),sendToTopic() 将其发送到所有订阅主题为 authorname 的用户(例如:Peter)

编辑后,我认为您希望用户取消订阅某个主题,但继续订阅其他主题,那么您必须为此使用 admin sdk:

https://firebase.google.com/docs/cloud-messaging/admin/manage-topic-subscriptions

使用 admin sdk,您也可以取消订阅用户的主题,一个简单的例子:

 // These registration tokens come from the client FCM SDKs.
var registrationTokens = [
 'YOUR_REGISTRATION_TOKEN_1',
 // ...
 'YOUR_REGISTRATION_TOKEN_n'
];

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
admin.messaging().unsubscribeFromTopic(registrationTokens, topic)
.then(function(response) {
  // See the MessagingTopicManagementResponse reference documentation
  // for the contents of response.
  console.log('Successfully unsubscribed from topic:', response);
 })
 .catch(function(error) {
   console.log('Error unsubscribing from topic:', error);
  });

【讨论】:

  • 对不起,我应该提到为什么我们没有在原始问题中使用主题。使用主题很棘手,因为我们需要考虑用户特定的通知设置。
  • @Sunny 当用户点击“不接收来自该主题的通知”然后使用管理员 SDK 并取消订阅他。在数据库中添加一个名为“subscribed”的字段,如果更改为false,则会触发onWrite并取消订阅
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-18
  • 2020-04-01
  • 2021-04-12
  • 1970-01-01
  • 2018-06-01
  • 2020-08-29
  • 1970-01-01
相关资源
最近更新 更多