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

时间:2018-09-01 09:23:34

标签: firebase data-structures nosql

说我的NoSQL结构如下:

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

我还拥有users/分支,可以在其中查看所涉及的两个用户的最新登录信息。
我想通过1个查询来获取给定用户的未读邮件数。

您将如何执行这样的任务?

2 个答案:

答案 0 :(得分:5)

此问题有两个部分:

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

计算邮件数

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

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

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

此时,您将切换为在数据库中保留一个计数器,并在每次写入/删除操作时对其进行更新。这会重复数据,因此具有关系数据库背景的开发人员通常会为此而苦恼。但这是最常见的方法。

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

跟踪用户阅读的内容

要知道用户有多少未读消息,您需要知道用户已经阅读了什么。同样,这里有两种常用方法:

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

跟踪单个消息听起来最正确,所以我看到了很多事情。我还看到开发人员为之苦苦挣扎,因为它涉及大量记账工作。绝对有可能,但是我建议从一个简单的方法开始...

聊天应用程序处理(按时间顺序)消息序列。如果您知道该用户已查看的最新消息的ID ,则可以假定该用户也已查看所有早于此消息的消息。

假设我跟踪了您阅读的最后一条消息的时间戳,它是1535725374298。现在,我可以查询聊天以仅检索比此更新的消息:

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

答案 1 :(得分:1)

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

现在,您要做的就是用。/users/$useronSnapshot()文档。客户端采取措施读取快照中的消息后,只需从users/$uid节点中删除该消息ID。

users/$uid中存储消息ID的方式(userDocument)由您决定-可以是数组,也可以是嵌套对象,甚至可以将消息ID单独存储为类型{ {1}},只要有一种方法可以识别reference客户端(因此您可以迭代doc字段以在实时快照中查找未读消息)。

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