【问题标题】:Firebase Realtime Database reach nested childFirebase 实时数据库到达嵌套子级
【发布时间】:2022-01-21 06:27:04
【问题描述】:

我正在构建一个项目,并且在这个项目中我进行了一对一的聊天。每个聊天都使用来自 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 的下方和下方。

知道在聊天集合中我们可以找到所有已经发送消息的用户。还知道每个这些都包含来自 currentUser 与之交互的所有用户的文档 (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()
        })
      })
      
    })
  })

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

感谢您的帮助!

【问题讨论】:

  • 您的代码查询publicChat,但您共享的 JSON 中不存在此类节点。应该是chat
  • "我尝试使用不同的方式联系他们,例如在 forEach 方法中直接调用数据库以对每个的 snapshot.id 进行分级,然后可能会获取 child().val() 但它没有st 似乎有效”您可以编辑您的问题以显示您尝试过的代码吗?

标签: javascript firebase react-native firebase-realtime-database google-cloud-functions


【解决方案1】:

如果您正在阅读整个 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 中删除(最好是多路径更新),这样这个节点也不会无限增长。

【讨论】:

  • 感谢您的帮助!到目前为止,我添加了一些我的不同之处的代码。明天我将尝试您的解决方案,因为存储 UID 似乎是更好的方法,而不是必须读取整个聊天节点。之后我会验证你的答案
  • 完美。我刚刚添加了第三种同样可行的方法。
  • 已经有一段时间了,但我使用了你的第三种方法,它非常适合我的情况!再次感谢
猜你喜欢
  • 2019-09-13
  • 2018-08-04
  • 2018-06-05
  • 2017-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多