如何根据ServerValue.TIMESTAMP排序并监听子节点结果?

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

我遇到了情况,Firebase 推送密钥 ID 不按时间顺序排列。

在他的回答的评论中,@FrankvanPuffelen 说

如果您遇到无法容忍此类问题的场景, 您还需要在子节点中写入服务器端时间戳, 并根据该值对结果进行排序

我当前的代码:

fun sendMessage(fromId: String, toId: String) {

    val messageId = Firebase.database.reference.child("messages").push().key.toString()

    val messageMap = mutableMapOf<String, Any>()
    messageMap["timeStamp"] = System.currentTimeMillis()
    messageMap["message"] = "..."
    messageMap["fromId"] = fromId
    messageMap["toId"] = toId
    messageMap["messageId"] = messageId

    val messagesRef = "/messages/$messageId"
    val fromIdRef = "/user-messages/$fromId/$toId/$messageId"
    val toIdRef = "/user-messages/$toId/$fromId/$messageId"

    val atomicMap = mutableMapOf<String, Any>()
    atomicMap[messagesRef] = messageMap
    atomicMap[fromIdRef] = 1
    atomicMap[toIdRef] = 1

    val rootDbRef = Firebase.database.reference
    rootDbRef.updateChildren(atomicMap)
}

结果是:

-messages
    -NseAh8_4jwiZ9CR9XXw
       message: "..."
       messageId: "-NseAh8_4jwiZ9CR9XXw"
       timeStamp: 1696624119048
       // ...

-user-messages
    -user_A
       user_B
          -NseAh8_4jwiZ9CR9XXw: 1
    -user_B
       user_A
          -NseAh8_4jwiZ9CR9XXw: 1

每当任何一个用户向另一个用户发送新消息时,我都会有一个侦听器来侦听 user-messages/the_current_uid/other_uid/last_message_Id,因此所有新消息当前都会向两个用户显示:

var userMessagesObserver = Firebase.database.reference.child("user-messages")

fun listenForNewMessages() {

    query = userMessagesObserver
                .child(fromId) // fromId is the current user
                .child(toId)   // toId is the other user they are messaging with
                .orderByKey()
                .limitToLast(1)

    listenerRefHandle = query?.addChildEventListener(object : ChildEventListener{

        override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {

            val lastMessageId = snapshot.key.toString()
            fetchMessage(lastMessageId)
        }
    })
}

fun fetchMessage(messageId: String) {
    // fetch message from messagesRef using the messageId then display it
}

根据弗兰克的建议,一旦我研究使用

ServerValue.TIMESTAMP
,它就不能用作
key
,只能用作,所以我不知道如何(1)将其添加到user-messages/the_current_uid/other_uid/last_message_Id 节点,因为无论发生什么,子节点的密钥始终是 messageId,例如。 -NseAh8_4jwiZ9CR9XXw:1,正如我的问题中所述,这可能会出现严重错误。 (2) 我如何收听新添加的
ServerValue.TIMESTAMP
,以便我知道何时显示新消息?

android firebase kotlin firebase-realtime-database timestamp
1个回答
0
投票

正如 @FrankvanPuffelen 建议的那样,最好在子节点中使用服务器端时间戳,并根据该时间戳对值进行排序。

正如我在你的代码中看到的:

messageMap["timeStamp"] = System.currentTimeMillis()

timeStamp
属性保存当前毫秒的值,但该值是在运行该代码的计算机上生成的,而不是在服务器上生成的。

根据 Frank 的建议,一旦我研究使用 ServerValue.TIMESTAMP,就不能用作键,只能用作值。

是的,您无法使用
ServerValue.TIMESTAMP

作为节点的名称。为什么?这是因为

ServerValue.TIMESTAMP
是一个对象,更好地说是
Map
,并且实时数据库中的键始终是字符串。 虽然这可能是可能的,但并没有多大帮助。实时数据库中的时间戳是用很长的数字来表示的,所以如果你设置一个数字作为键,它就会变成一个字符串,如果你想对字符串进行排序,你不会得到想要的结果,因为当你对字符串进行排序时,字符串按字典顺序

排序。

正如之前所说,最好的选择是将时间戳添加为字段的值。在 Kotlin 中,它会很简单:

在 Kotlin 中将数据类的对象添加到 Firestore 时如何添加 Firebase 时间戳?
  • 现在,您可以创建一个查询并
  • 按子项对结果进行排序

有一个下行站点,不幸的是,您无法像在 Firestore 中那样指定方向。因此,您不能要求实时数据库按降序返回元素。所以这里的技巧是添加负值。这意味着当您的订单中有负数元素升序时,您会得到所需的结果。

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