Reputation: 1374
I have web app to get realtime updates of documents from a collection. But the collection size is too high. So getting data without applying limit not possible and not effective. So it is very important to implement some limit on query. Right now i am taking the data as a chunk of 50. I have gone trough the reference Firestore reactive pagination . The logic explained in this link working in good manner.
But there is a confusion in below code that how the document read will be calculated here. Because according to the code first i am getting documents using normal get()
method as a chunk of 50 documents.After that i am attaching a listener to the response from the get()
method.So will Firestore add extra 50 reads or just 50?
Here is the code what i have done
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())
}
Upvotes: 4
Views: 1212
Reputation: 317427
This will cost 50 document reads:
ref.orderBy('createdAt', 'desc').limit(50).get()
Then this will again cost at least the same number of document reads:
ref.orderBy('createdAt').startAt(start).endBefore(end).onSnapshot(...)
Or possibly more, depending on how often those documents are updated while the listener is active.
Firestore doesn't offer an easy way to do realtime updates at the same time as pagination. Custom solutions like this will be costly like this.
Upvotes: 2