假设我有如下NoSQL结构:
messages chat_id (known) message_id (generated automatically) {author, timestamp, content}
我还有一个users/分支,在那里我可以看到涉及的两个用户的最后登录。我想通过1个查询获得给定用户的未读邮件数。您将如何执行这样的任务?
users/
4si2a6ki1#
这个问题有两个部分:1.计算消息数1.跟踪用户已阅读的内容
假设您使用的是Firebase Realtime Database或Cloud Firestore,则有两种典型的计数方法:1.在客户端加载未读消息并计数。1.在数据库中保留一个消息计数器,并在每次读/写消息时更新该计数器。
在客户端计算消息是最容易实现的,所以通常是没有经验的开发人员开始使用的。当消息数量较少时,这很好。但是随着消息数量的增加,您将下载越来越多的数据。
此时,您将切换到在数据库中保留一个计数器,并在每次写入/删除操作时更新它。这会复制数据,因此通常是具有关系数据库背景的开发人员难以解决的问题。但这是最常见的方法。您可以更新计数器客户端,或者使用服务器端方法,如example of maintaining counters in Cloud Functions。
要了解用户有多少未读邮件,需要知道用户已经读了哪些邮件。这里,有两种常见的方法:1.跟踪用户已阅读的每封邮件。1.跟踪用户最近阅读的邮件的ID。跟踪单个消息听起来是最正确的,所以我看到很多人这样做。我也看到开发人员在努力解决这个问题,因为它涉及到大量的簿记工作。这肯定是可能的,但我建议从一个更简单的方法开始...聊天应用处理(按时间顺序)的消息序列。如果你知道用户看到的最新消息的ID,你可以假设用户也看到了比这个更早的所有消息。假设我跟踪了您阅读的最后一条消息的时间戳,它是1535725374298。现在我可以查询聊天,以便只检索比该时间晚的消息:
1535725374298
firebase.database() .ref("chat") .child(chatId) .orderByChild("timestamp") .startAt(1535725374298)
rekjcdws2#
如果您使用Firebase Authentication的用户id和uid,它可以为不同设备的用户提供一致的uid,那么将消息id设置为/users/$uid文档是可行的方法。现在,您所要做的就是使用. onSnapshot()监听/users/$user文档。一旦客户端采取行动读取快照中的消息,只需从users/$uid节点中删除该消息id。如何在users/$uid(userDocument)中存储消息ID由您决定-可以是数组,也可以是嵌套对象,甚至可以将消息ID单独存储为reference类型,前提是有一种方法可以标识type == reference客户端(这样您就可以迭代doc字段,在实时快照中查找未读消息)。这样做的好处是你简化了你的代码/系统。让Firebase在更新(新的未读消息)发生时向你发送更新。
/users/$uid
onSnapshot()
/users/$user
users/$uid
reference
type == reference
oknrviil3#
如果添加已阅读消息的用户的列表字段(Firebase中的Array
{"author": "someUserId", "timestamp": 1324134123, "content": "some message...", "readByUsers": ["someUserId", "someOtherUserId"]}
然后通过查询获得所有消息的列表(这可能是您已经在做的事情),通过简单地获得列表的长度来计算total_messages的列表。然后,通过执行类似下面的操作(本示例使用Dart,但只搜索首选语言的列表理解),获得已阅读的所有消息的计数。
var read_message_count= all_messages.where((x) => x.readByUsers.contains("someUserId")).toList().length;
未读消息总数=所有消息长度-已读消息计数Firebase很有挑战性,因为它对每个字段都进行了索引,所以您无法查询“不包含”某些内容的消息。您必须查询用户已经阅读的消息的计数,然后从总数中减去该计数。如果您使用我建议的设计,那么您只需查询Firebase一次。但它将在最终用户的设备上进行一些本地处理。
3条答案
按热度按时间4si2a6ki1#
这个问题有两个部分:
1.计算消息数
1.跟踪用户已阅读的内容
计算消息数
假设您使用的是Firebase Realtime Database或Cloud Firestore,则有两种典型的计数方法:
1.在客户端加载未读消息并计数。
1.在数据库中保留一个消息计数器,并在每次读/写消息时更新该计数器。
在客户端计算消息是最容易实现的,所以通常是没有经验的开发人员开始使用的。当消息数量较少时,这很好。但是随着消息数量的增加,您将下载越来越多的数据。
此时,您将切换到在数据库中保留一个计数器,并在每次写入/删除操作时更新它。这会复制数据,因此通常是具有关系数据库背景的开发人员难以解决的问题。但这是最常见的方法。
您可以更新计数器客户端,或者使用服务器端方法,如example of maintaining counters in Cloud Functions。
跟踪用户已阅读的内容
要了解用户有多少未读邮件,需要知道用户已经读了哪些邮件。这里,有两种常见的方法:
1.跟踪用户已阅读的每封邮件。
1.跟踪用户最近阅读的邮件的ID。
跟踪单个消息听起来是最正确的,所以我看到很多人这样做。我也看到开发人员在努力解决这个问题,因为它涉及到大量的簿记工作。这肯定是可能的,但我建议从一个更简单的方法开始...
聊天应用处理(按时间顺序)的消息序列。如果你知道用户看到的最新消息的ID,你可以假设用户也看到了比这个更早的所有消息。
假设我跟踪了您阅读的最后一条消息的时间戳,它是
1535725374298
。现在我可以查询聊天,以便只检索比该时间晚的消息:rekjcdws2#
如果您使用Firebase Authentication的用户id和uid,它可以为不同设备的用户提供一致的uid,那么将消息id设置为
/users/$uid
文档是可行的方法。现在,您所要做的就是使用.
onSnapshot()
监听/users/$user
文档。一旦客户端采取行动读取快照中的消息,只需从users/$uid
节点中删除该消息id。如何在
users/$uid
(userDocument)中存储消息ID由您决定-可以是数组,也可以是嵌套对象,甚至可以将消息ID单独存储为reference
类型,前提是有一种方法可以标识type == reference
客户端(这样您就可以迭代doc字段,在实时快照中查找未读消息)。这样做的好处是你简化了你的代码/系统。让Firebase在更新(新的未读消息)发生时向你发送更新。
oknrviil3#
如果添加已阅读消息的用户的列表字段(Firebase中的Array
然后通过查询获得所有消息的列表(这可能是您已经在做的事情),通过简单地获得列表的长度来计算total_messages的列表。
然后,通过执行类似下面的操作(本示例使用Dart,但只搜索首选语言的列表理解),获得已阅读的所有消息的计数。
未读消息总数=所有消息长度-已读消息计数
Firebase很有挑战性,因为它对每个字段都进行了索引,所以您无法查询“不包含”某些内容的消息。您必须查询用户已经阅读的消息的计数,然后从总数中减去该计数。如果您使用我建议的设计,那么您只需查询Firebase一次。但它将在最终用户的设备上进行一些本地处理。