【问题标题】:Is it possible if I can get the last key (latest message) added from the realtime database?如果我可以从实时数据库中获取最后一个键(最新消息),是否有可能?
【发布时间】:2021-10-07 01:04:51
【问题描述】:

我想从我的实时数据库中获取最后一个密钥(最新消息),但不确定如何实现。 我从这个链接i need to get Last child of my firebase databse 看到我可以使用 orderByKey().limitToLast(1) 来获得它,但看起来我需要指定完整的 ref 才能实现这一点。那是对的吗?或者如果我可以在 val() 上 orderByKey().limitToLast(1) 有可能吗?还是有另一种方法可以实现这一目标? 这是我在数据库中的消息结构:

我在每个键下都有一个时间戳子,如上所示,我想我可以查询它以提取最新的键,但我真的不知道该怎么做。有人可以帮忙吗?以下是我目前的代码:

database().ref(`messages/`).once(`value`, snapshot => {
 if(snapshot.exists()) {
   snapshot.forEach(function (childSnapshot) {
      if(childSnapshot.key.includes(auth().currentUser.uid)) {
      console.log("show me the key: "+childSnapshot.key)

      //not working
      console.log("show last message: "+ JSON.stringify(childSnapshot.val().orderbyKey().limitToLast(1)))
      }
    })
  }
})

console.log(JSON.stringify(messages)) => [{"-MfqYBzbusp1Cljgxpan":{"unreadMessage":true,"user":{"name":"Mike","avatar":"xxxxxx" ,"_id":"tFhmw5oQoPhk8nF2sx5rE5BFqw93"},"timestamp":1627634061437,"senderId":"tFhmw5oQoPhk8nF2sx5rE5BFqw93","notification":{"body":"Hey","title":"Project","imageUrl":" ./assets/xxxxx.png"},"text":"嘿"}}]

console.log(JSON.stringify(unreadMsgs)) => []

【问题讨论】:

    标签: javascript firebase firebase-realtime-database


    【解决方案1】:

    Firebase 实时数据库查询适用于平面节点列表。因此,如果您已经有特定路径 /messages/nodeid,您可以在该路径下找到最新消息,但您无法在所有 /messages 中找到最新消息。

    读取来自所有聊天室的所有消息,只是为了找到该用户所在的每个聊天室的最新消息确实很浪费。随着您向应用中添加更多用户,您会增加他们的带宽成本,也会增加您自己的带宽成本。

    我建议保留一个单独的节点来跟踪每个用户的聊天室,正如我在Best way to manage Chat channels in Firebase 上的回答中所解释的那样。使用这样的节点,您可以轻松地确定当前用户的聊天室,然后为每个用户加载最新消息,例如:

    database().ref(`user_chatrooms/${auth().currentUser.uid}`).once(`value`, indexSnapshot => {
      indexSnapshot.forEach((indexSnapshotChild) => {
        let chatroomId = indexSnapshotChild.key;
        let query = database().ref(`messages/${chatroomId}`).orderByChild("timestamp").limitToLast(1)
        query.once(`value`, (msgSnapshot) => {
          console.log(`Last message in ${chatroomId} was ${msgSnapshot.val().text}`);
        })
      }
    })
    

    【讨论】:

      【解决方案2】:

      orderByKeylimitToLast 方法存在于 DatabaseReference 上,而不是您从之前获取的快照中获取的值上。似乎所有消息的父键格式为userId1userId2。如果您知道这种组合,那么您可以通过这种方式运行查询。

      const uidsKey = "uid1" + "uid2"
      const query = database().ref(`messages/${uidsKey}`).orderByChild("timestamp").limitToLast(1)
      
      query.once("value").then((snapshot) => {
        console.log(snapshot.val())
      })
      

      但您似乎正在尝试获取与 user1 聊天的其他用户的 UID,并尝试首先访问所有节点。我不建议这样做,因为这可能会导致安全规则等问题。相反,如果您将这些 UID 列表保留在其他地方,那就更好了。但是如果你想保留你现在拥有的东西,试试这个:

      const userUID = auth().currentUser.uid
      
      database().ref("messages/").once("value").then(async (msgSnapshot) => {
        const keys = Object.keys(msgSnapshot.val() || {})
        const userChatKeys = keys.filter(k => k.includes(userUID))
        //const otherUserIDs = userChatKeys.map(k => k.replace(userUID, ""))
      
        //userChatKeys will be chat IDs where current user is included
        //now follow the same steps mentioned in first code snippet
        const queries = userChatKeys.map(chat => database().ref(`messages/${chat}`).orderByChild("timestamp").limitToLast(1).once("value"))
        const lastMessagesSnap = await Promise.all(queries)
        
        const messages = lastMessagesSnap.map(m => Object.values(m.val())[0])) 
        console.log(`messages: ${messages}`)
        const unreadMsgs = messages.filter((msg) => msg.unreadMessage === true)
        console.log(unreadMsgs.length)
      })
      

      这将记录每个用户聊天的最后一条消息。

      【讨论】:

      • 感谢您的回复。这似乎不起作用。时间戳在另一个键下(消息 -> uid1+uid2 键 -> 消息键 -> 时间戳)。 orderByChild 仍然可以为此工作。我收到错误“m.val 不是函数”。 (在 'm.val()' 中,'m.val' 未定义)'
      • @AJDee 你能登录userChatKeys 并分享输出吗?您是否获得了家长聊天 ID?
      • 是的,我是。 [ “GjiGzmEX3yOgvyyyUHDHER1mSoE2tFhmw5oQoPhk8nF2sx5rE5BFqw93”, “h3kIhXphkQUSPhTibEgU0YsxStI2tFhmw5oQoPhk8nF2sx5rE5BFqw93”, “I9tpdxGQodf3TE8JpLtefn0XTGJ2tFhmw5oQoPhk8nF2sx5rE5BFqw93”, “OGLjfTllh4b3eIHRFkLhBX3CrZn1tFhmw5oQoPhk8nF2sx5rE5BFqw93”, “Ysrux9flYbRatW14pRFKFb471Tz2tFhmw5oQoPhk8nF2sx5rE5BFqw93”, “q2dggRbm5aVl1ZXXB7wg6Db7I0i1tFhmw5oQoPhk8nF2sx5rE5BFqw93”] 跨度>
      • @AJDee 哦,我明白了。我忘了在该地图函数中添加.once("value")。请立即尝试。应该是const queries = userChatKeys.map(chat => database().ref(`messages/${chat}`).orderByChild("timestamp").limitToLast(1).once("value"))
      • 非常感谢我现在可以看到该对象,但是如何检查 unreadMessage 的值?不管是假的还是真的?本质上,我只想获取未读消息的计数。 m.val().unreadMessage 不这样做。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 2012-07-15
      • 1970-01-01
      相关资源
      最近更新 更多