【问题标题】:Firestore: What is the efficient way to list messages in chat?Firestore:在聊天中列出消息的有效方法是什么?
【发布时间】:2020-03-14 10:47:16
【问题描述】:

我正在尝试使用 Firestore 创建一个类似聊天的应用程序,并尝试列出聊天中的所有消息,并在每次添加消息时更新它。

我首先尝试了这种方式来实现它。

mounted() {

    docRef.collection('messages').orderBy('timestamp', 'desc').limit(1).onSnapshot((querySnapShot) => {
        querySnapShot.forEach((doc) => {
            if (!doc.metadata.hasPendingWrites) {
                this.messages.push(doc.data())
            }
        })
    })

}

这种方式似乎很有效,因为这种方式只能获取集合中的最新消息。但是,我发现这种方式有问题。当用户刷新页面时,用户无法获取过去的消息。

所以我就这样改了。

mounted() {
    docRef.collection('messages').orderBy('timestamp', 'asc').onSnapshot((querySnapShot) => {
        querySnapShot.docChanges().forEach((change) => {
            if (change.type === 'added') {
                 this.messages.push(change.doc.data())
              }
        })
    })
}

这种方式按我的预期工作。但是这种方式需要很多请求,因为每次更改集合时我都需要读取集合中的所有文档。

在聊天中列出消息的有效方法是什么?

我认为如果我首先获取所有当前消息并设置新消息的侦听器,但即使集合中没有变化并阅读最新消息两次,在我进入页面后立即触发侦听器。

【问题讨论】:

  • 好问题...对“hasPendingWrites”一无所知,很困惑为什么它会打印多次并说我的新消息已“修改”

标签: javascript firebase vue.js google-cloud-firestore


【解决方案1】:

我最终只是使用一个标志来检查初始触发是否完成。我不知道这是否是聪明的方式,但这是可行的。

// Get all current messages
  docRef.collection('messages').orderBy('timestamp', 'asc').get().then((querySnapShot) => {
    querySnapShot.forEach((doc) => {
      this.messages.push(doc.data())
    })
  })

// Update for new messages (Skip the initial loading)

  docRef.collection('messages').orderBy('timestamp', 'desc').limit(1).onSnapshot((querySnapShot) => {
      querySnapShot.forEach((doc) => {
        if (!doc.metadata.hasPendingWrites && this.isInitialDone) {
          this.messages.push(doc.data())
        }
        this.isInitialDone = true
      })
  })

【讨论】:

    【解决方案2】:

    您将需要设置适当的限制,或添加过滤器以确定您想要的限制。

    如果您想使用大小限制,只需将第一个查询中的 limit(1) 更改为您实际需要的数字即可。

    如果您想使用过滤器,您可能应该使用已有的时间戳来确定您想要回到过去多远。

    这是限制结果大小的两个选项。您可以使用其中之一或同时使用两者,但没有其他方法可以限制结果集的大小。

    【讨论】:

    • 我设置了第一种方式的限制,但是这种方式在页面刷新时无法获取过去的消息。但是对于第二种方式,我需要在每次发生变化时读取集合中的所有消息。
    • 第二种方式不需要阅读所有消息。如果使用范围过滤器(、=),它只会读取指定范围内的文档。你确定范围,或者你想去多远的过去。 firebase.google.com/docs/firestore/query-data/…
    • 但是如果我为第二种方式设置了限制,如果用户刷新屏幕,用户将无法收到所有消息。
    • 是的,您将不得不选择其中一个或同时使用两个,直到您对结果感到满意为止。
    猜你喜欢
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    • 2019-04-09
    • 2021-04-29
    • 2019-08-14
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    相关资源
    最近更新 更多