firestore onsnapshotListner с разбивкой на страницы - PullRequest
0 голосов
/ 08 мая 2020

У меня есть веб-приложение для получения обновлений документов из коллекции в реальном времени. Но размер коллекции слишком велик. Таким образом, получение данных без ограничения невозможно и неэффективно. Поэтому очень важно установить некоторые ограничения на запросы. Прямо сейчас я беру данные как кусок из 50. Я прошел через ссылку реактивная разбивка на страницы Firestore . Лог c, объясненный в этой ссылке, работает хорошо.

Но в приведенном ниже коде есть путаница в том, как здесь будет рассчитываться прочитанный документ. Потому что, согласно коду, сначала я получаю документы обычным методом get() в виде блока из 50 документов. После этого я прикрепляю слушателя к ответу от метода get(). Таким образом, Firestore добавит дополнительные 50 операций чтения или только 50. ?

Вот код, который я сделал

var messages = [] 
var listeners = []    // list of listeners
var start = null      // start position of listener
var end = null        // end position of listener

function getMessages(chatId) {

// query reference for the messages we want

let ref = db.collection('chats').doc(chatId)
.collection('messages')

// single query to get startAt snapshot

ref.orderBy('createdAt', 'desc')
.limit(50).get()
.then((snapshots) => {

// save startAt snapshot

start = snapshots.docs[snapshots.docs.length - 1]

// create listener using startAt snapshot (starting boundary)

let listener = ref.orderBy('createdAt')
  .startAt(start)
  .onSnapshot((messages) => {
    // append new messages to message array
    messages.forEach((message) => {
      // filter out any duplicates (from modify/delete events)         
      messages = messages.filter(x => x.id !== message.id)
      messages.push(message.data())
    })
  })

  // add listener to list

  listeners.push(listener)
})
}


 function getMoreMessages(chatId) {

let ref = db.collection('chats').doc(chatId)
.collection('messages')

// single query to get new startAt snapshot

ref.orderBy('createdAt', 'desc')
.startAt(start)
.limit(50).get()
.then((snapshots) => {

 // previous starting boundary becomes new ending boundary

  end = start
  start = snapshots.docs[snapshots.docs.length - 1]

  // create another listener using new boundaries     

  let listener = ref.orderBy('createdAt')
  .startAt(start).endBefore(end)
  .onSnapshot((messages) => {
    messages.forEach((message) => {
      messages = messages.filter(x => x.id !== message.id)
      messages.push(message.data())
    })
  })
  listeners.push(listener)
})
}

// call to detach all listeners
function detachListeners() {
 listeners.forEach(listener => listener())
 }

1 Ответ

1 голос
/ 08 мая 2020

Это будет стоить 50 чтений документа:

ref.orderBy('createdAt', 'desc').limit(50).get()

Тогда это снова будет стоить как минимум такое же количество чтений документа:

ref.orderBy('createdAt').startAt(start).endBefore(end).onSnapshot(...)

Или, возможно, больше, в зависимости от того, как часто эти документы обновляются, пока активен слушатель.

Firestore не предлагает простой способ делать обновления в реальном времени одновременно с разбивкой на страницы. Подобные нестандартные решения будут такими же дорогостоящими.

...