如何通过1个查询构造NoSQL消息以获取未读?

问题描述 投票:1回答:2

说我有NoSQL结构如下:

messages  
  chat_id (known)  
    message_id (generated automatically)  
      {author, timestamp, content}

我也有users/分支,我可以看到两个用户的最后登录。 我想通过1个查询获取给定用户的未读消息数。

你会如何实现这样的任务?

firebase data-structures nosql
2个回答
5
投票

这个问题有两个部分:

  1. 计算消息数量
  2. 跟踪用户阅读的内容

Counting the number of messages

假设您使用的是Firebase实时数据库或Cloud Firestore,则有两种典型的计数方法:

  1. 加载未读消息并将其计入客户端。
  2. 保留数据库中消息的计数器,并在每次读取/写入消息时更新消息。

计算客户端的消息最容易实现,因此通常缺乏经验的开发人员开始。当消息数量很少时,这样可以正常工作。但随着消息数量的增加,您将下载越来越多的数据。

此时,您将切换到在数据库中保留计数器并在每次写入/删除操作时更新该计数器。这会复制数据,因此通常是关系数据库中具有背景的开发人员会遇到的问题。但这是最常见的方法。

您可以更新计数器客户端,或使用服务器端方法,例如此example of maintaining counters in Cloud Functions

Tracking what the user has read

要知道用户有多少未读消息,您需要知道用户已经读过的内容。在这里,有两种常见的方法:

  1. 跟踪用户已阅读的每条消息。
  2. 跟踪用户已阅读的最新消息的ID。

跟踪单个消息听起来最正确,所以我看到这样做很多。我也看到开发人员正在努力解决它,因为它涉及大量的簿记。这绝对是可能的,但我建议从更简单的方法开始......

聊天应用处理(按时间顺序)消息序列。如果您知道用户看到的最新消息的ID,则可以假设用户还看到了所有早于此消息的消息。

假设我跟踪你读到的最后一条消息的时间戳,它是1535725374298。我现在可以查询聊天,只检索比这更新的消息:

firebase.database()
  .ref("chat")
  .child(chatId)
  .orderByChild("timestamp")
  .startAt(1535725374298)

1
投票

如果您使用Firebase身份验证的用户ID,即uid,它为跨设备的用户提供一致的uid,则将消息ID设置为/users/$uid文档即可。

现在,您所要做的就是使用./users/$user收听onSnapshot()文档。客户端采取操作读取快照中的消息后,只需从users/$uid节点中删除该消息ID即可。

你如何在users/$uid(userDocument)中存储消息id取决于你 - 可以是一个数组,也可以是一个嵌套对象,甚至可以将消息id单独存储为类型reference,前提是有办法识别type == reference客户端(因此您可以迭代doc字段,在实时快照中查找未读消息)。

这样做的好处是可以简化代码/系统。让Firebase在发生时向您发送更新(新的未读邮件)。

© www.soinside.com 2019 - 2024. All rights reserved.