说我有NoSQL结构如下:
messages
chat_id (known)
message_id (generated automatically)
{author, timestamp, content}
我也有users/
分支,我可以看到两个用户的最后登录。
我想通过1个查询获取给定用户的未读消息数。
你会如何实现这样的任务?
这个问题有两个部分:
假设您使用的是Firebase实时数据库或Cloud Firestore,则有两种典型的计数方法:
计算客户端的消息最容易实现,因此通常缺乏经验的开发人员开始。当消息数量很少时,这样可以正常工作。但随着消息数量的增加,您将下载越来越多的数据。
此时,您将切换到在数据库中保留计数器并在每次写入/删除操作时更新该计数器。这会复制数据,因此通常是关系数据库中具有背景的开发人员会遇到的问题。但这是最常见的方法。
您可以更新计数器客户端,或使用服务器端方法,例如此example of maintaining counters in Cloud Functions。
要知道用户有多少未读消息,您需要知道用户已经读过的内容。在这里,有两种常见的方法:
跟踪单个消息听起来最正确,所以我看到这样做很多。我也看到开发人员正在努力解决它,因为它涉及大量的簿记。这绝对是可能的,但我建议从更简单的方法开始......
聊天应用处理(按时间顺序)消息序列。如果您知道用户看到的最新消息的ID,则可以假设用户还看到了所有早于此消息的消息。
假设我跟踪你读到的最后一条消息的时间戳,它是1535725374298
。我现在可以查询聊天,只检索比这更新的消息:
firebase.database()
.ref("chat")
.child(chatId)
.orderByChild("timestamp")
.startAt(1535725374298)
如果您使用Firebase身份验证的用户ID,即uid,它为跨设备的用户提供一致的uid,则将消息ID设置为/users/$uid
文档即可。
现在,您所要做的就是使用./users/$user
收听onSnapshot()
文档。客户端采取操作读取快照中的消息后,只需从users/$uid
节点中删除该消息ID即可。
你如何在users/$uid
(userDocument)中存储消息id取决于你 - 可以是一个数组,也可以是一个嵌套对象,甚至可以将消息id单独存储为类型reference
,前提是有办法识别type == reference
客户端(因此您可以迭代doc字段,在实时快照中查找未读消息)。
这样做的好处是可以简化代码/系统。让Firebase在发生时向您发送更新(新的未读邮件)。