Firebase 实时数据库到达嵌套子级

Firebase Realtime Database reach nested child

我正在构建一个项目,在这个项目中我进行了一对一的聊天。每个聊天记录都使用来自 firebase 的实时数据库存储(我在这里使用 react-native-firebase 库)。

我的数据树目前看起来像这样:

我们有类似的东西:chat/{currentUserID}/{userID} 然后消息存储在这里并使用自动生成 ID 的 push() 方法发送到数据库。

基本上我想做的是通过删除超过 7 天前的所有消息来进行一些清理。 我已经有了这方面的逻辑,我在这里为我的应用程序的另一部分做这件事:

const randomTestTimerDB = Date.now() - 1

admin.database()
  .ref('/publicChat')
  .orderByChild('timestamp')
  .endAt(randomTestTimerDB)
  .once('value')
  .then((snapshot) => {
    snapshot.forEach((snap) => {
    snap.ref.remove()
     })
   })

这很好用。但是我这里的问题是我正在使用云函数来做到这一点,所以我无法跟随我的树到达它们,因为它们嵌套在我没有的 ID 的下方和下方。

知道在聊天集合中我们可以找到所有已经发送消息的用户。还知道每个文档都包含当前用户与之交互的所有用户的文档(userID),在每个文档下面,附加到 userID 文档,我们最终得到了这两个用户之间共享的所有消息。

我尝试使用不同的方式来联系他们,比如直接在 forEach 方法中调用数据库来对每个的 snapshot.id 进行分级,然后可能会得到 child().val() 但它似乎并没有上班。

这是我到目前为止尝试过的代码:

admin.database()
  .ref('/chat')
  .once('value')
  .then((snapshot) => {
    snapshot.forEach((snap) => {
      if(snap.child().val().timestamp <= randomTestTimerDB) {
        snap.ref.remove()
    }
      
    })
  })
admin.database()
  .ref('/chat')
  .once('value')
  .then((snapshot) => {
    snapshot.forEach((snap) => {
      admin.database().ref(`/chat/${snap.id}`).orderByChild('timestamp').endAt(randomTestTimerDB).once('value').then((snp) => {
        snp.forEach((eachSnp) => {
          eachSnp.ref.remove()
        })
      })
      
    })
  })

我怎样才能以最简单的方式获取那些嵌套的消息?如果这甚至可能,或者我是否应该考虑另一种方法来存储和组织我的数据树以使其更容易?

感谢您的帮助!

如果您正在阅读整个 chat 节点,您可以像这样遍历各个级别:

admin.database().ref('/chat').once('value').then((snapshot) => {
  snapshot.forEach((user1Snapshot) => {
    user1Snapshot.forEach((user2Snapshot) => {
      console.log(`Chat between ${user1Snapshot.key} and {$user2Snapshot.key}`);
      // TODO: perform a query on user2Snaphot.ref
    })
  })
})

虽然这会读取整个 chats 节点,包括您不打算删除的消息。


如果您只想读取要删除的数据,则必须已经知道 chats.

下存在的所有 UID 对

最好的方法是将 UID 对也存储在某个地方,这样您就可以访问它们而无需下载所有聊天消息。所以像:

"existing_chats": {
  "$uid1_$uid2": true,
  "$uid2_$uid3": true
}

现在您可以从该结构中读取 UID 对,遍历它们,然后对每一对执行截断查询。


最后,您还可以考虑将所有消息的路径和过期时间戳作为它们的值保留一个平面列表:

"message_expirations": {
  "$uid1_$uid2_$messageid1": 127864586723459,
  "$uid1_$uid2_$messageid2": 127864586723469,
  ...
}

有了这个,您可以使用 orderByValue 对过期邮件进行一次查询,然后将它们全部删除。虽然它会导致最多的数据重复,但它是您的用例在数据结构中最直接的表示,我经常发现它最容易维护。

如果您选择这种方法,请不要忘记也从 message_expirations 中删除过期节点(最好使用多路径更新),这样该节点也不会无限增长。