我如何构建Firebase FCM令牌存储以实现扩展?

我如何构建Firebase FCM令牌存储以实现扩展?,firebase,google-cloud-firestore,firebase-cloud-messaging,Firebase,Google Cloud Firestore,Firebase Cloud Messaging,我的网络应用程序将有一个基于“线程”和“消息”的聊天功能 在任何给定的线程中,2个或更多人可以订阅新消息的通知 任何给定的人都可以拥有多个设备,每个设备都具有相应的FCM令牌(在授予向他们发送通知的权限后获得) 假设我有一个有3个订户的帖子“猫”。文档结构如下: id: "thread1" title: "cats" subscribers:["uid1","uid2","uid3"] id: "token1" tokenOwner: "uid1" id: "token2" t

我的网络应用程序将有一个基于“线程”和“消息”的聊天功能

在任何给定的线程中,2个或更多人可以订阅新消息的通知

任何给定的人都可以拥有多个设备,每个设备都具有相应的FCM令牌(在授予向他们发送通知的权限后获得)

假设我有一个有3个订户的帖子“猫”。文档结构如下:

id: "thread1"
  title: "cats"
  subscribers:["uid1","uid2","uid3"]
id: "token1"
  tokenOwner: "uid1"
id: "token2"
  tokenOwner: "uid2"
id: "token3"
  tokenOwner: "uid2"
id: "token4"
  tokenOwner: "uid3"
id: "token5"
  tokenOwner: "uid4"
db
  .collection("fcmTokens")
  .where('tokenOwner', 'in', ["uid1","uid2","uid3"])
  .get()...
我为这三个用户存储了FCM代币。文档结构如下:

id: "thread1"
  title: "cats"
  subscribers:["uid1","uid2","uid3"]
id: "token1"
  tokenOwner: "uid1"
id: "token2"
  tokenOwner: "uid2"
id: "token3"
  tokenOwner: "uid2"
id: "token4"
  tokenOwner: "uid3"
id: "token5"
  tokenOwner: "uid4"
db
  .collection("fcmTokens")
  .where('tokenOwner', 'in', ["uid1","uid2","uid3"])
  .get()...
要在
thread1
中发送新消息的通知,我需要在FCM令牌集合中查询
tokenOwner
位于提供的数组
[“uid1”、“uid2”、“uid3”]
中的任何令牌

该查询将如下所示:

id: "thread1"
  title: "cats"
  subscribers:["uid1","uid2","uid3"]
id: "token1"
  tokenOwner: "uid1"
id: "token2"
  tokenOwner: "uid2"
id: "token3"
  tokenOwner: "uid2"
id: "token4"
  tokenOwner: "uid3"
id: "token5"
  tokenOwner: "uid4"
db
  .collection("fcmTokens")
  .where('tokenOwner', 'in', ["uid1","uid2","uid3"])
  .get()...
在云Firestore查询限制生效之前,这非常有效:

使用in运算符可以组合上最多10个相等(=)子句 与逻辑OR相同的字段。in查询返回文档,其中 给定字段与任何比较值匹配

我最多只能在数组查询中包含10个uid。如果12个人订阅了该线程,我要么运气不佳,要么需要运行多个查询,这似乎效率低下


如何以“Firebase友好”的方式构造FCM令牌?

针对这种情况运行多个查询并不是很低效。所有请求都是通过单个连接进行管道传输的,您应该能够通过快速连接在毫秒内获取所有请求。新的“in”查询主要是为了方便用户不必执行多个查询,而不是为了优化(除非它阻止您从多个查询中多次获取同一文档)。你应该对你现在所拥有的一切都很满意——在你真正观察到性能问题之前,没有必要过早地优化它

就个人而言,我会将用户的令牌存储在用户的UID下,而不是将所有用户的令牌放在一个集合中

Collection: user-tokens
  Document ID: {uid}
    - tokens: [ array of tokens for the user ]
然后,要获取用户的所有令牌,只需获取包含所有令牌的文档即可

如果您担心用户可能正在使用数千台设备,并且令牌的数量可能超过单个文档的容量,请将每个令牌存储在单独的文档中,并在整个子集合中查询用户的令牌:

Collection: user-tokens
  Document ID: {uid}
    Subcollection: tokens
      Document ID: {random}
        - token: string

在UID下组织令牌还可以更容易地编写安全规则,以便只有特定用户可以读取和写入自己的令牌,如果这是您希望控制的事情。

仅在此说明,这种方法的限制是,当线程中的用户越多时,读取请求(成本也会增加)