Javascript Firestore:在聊天室中列出消息的有效方式是什么?

Javascript Firestore:在聊天室中列出消息的有效方式是什么?,javascript,firebase,vue.js,google-cloud-firestore,Javascript,Firebase,Vue.js,Google Cloud Firestore,我正在尝试使用Firestore创建一个类似聊天的应用程序,并尝试列出聊天中的所有消息,并在每次添加消息时进行更新 我首先尝试了这种方法来实现它 mounted() { docRef.collection('messages').orderBy('timestamp', 'desc').limit(1).onSnapshot((querySnapShot) => { querySnapShot.forEach((doc) => { i

我正在尝试使用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())
              }
        })
    })
}
这种方法正如我所预料的那样有效。但这种方式需要大量请求,因为每次更改集合时,我都需要阅读集合中的所有文档

在聊天室中列出消息的有效方式是什么


我认为如果我首先获取所有当前消息并设置新消息的侦听器,那么它会起作用,但在我进入页面后,侦听器会立即被触发,即使集合中没有任何更改,并读取两次最新消息。

您需要设置适当的限制,或者添加一个过滤器来确定您想要的

如果您想使用大小限制,只需在第一次查询中将
limit(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
      })
  })


我在第一种方式中设置了限制,但这种方式在刷新页面时无法获取过去的消息。但是对于第二种方法,每次发生更改时,我都需要读取集合中的所有消息。第二种方法不需要读取所有消息。如果使用范围筛选器(,=),它将仅读取指定范围内的文档。你决定了你要走的距离,或者你想走多远。但是如果我为第二种方法设置了限制,那么如果用户刷新屏幕,用户就无法获得所有消息。是的,你必须选择其中一种,或者同时使用这两种方法,直到你对结果感到满意。好问题……不知道“hasPendingWrites”我很困惑,为什么它要打印多次,并说我的新消息被“修改”