问题
Im building a chat feature for my app using Firestore. I'm using limit(toLast:) because I'm fetching based on the timestamp, this method gives me the latest messages saved in my DB. But it is giving me trouble when trying to fetch the snapshot/documents prior to that for loading older messages. Heres my code:
fileprivate func paginateFetchMessages() {
var query: Query!
if let nextStartingSnap = self.lastDocumentSnapshot {
query = DBCall.fireRef.collection("friendMessages")
.document(currentUID)
.collection(friendUID)
.order(by: "timestamp").limit(toLast: 5).start(afterDocument: nextStartingSnap)
} else {
query = DBCall.fireRef.collection("friendMessages")
.document(currentUID)
.collection(friendUID)
.order(by: "timestamp").limit(toLast: 5)
}
query.addSnapshotListener { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
guard let lastSnap = snapshot.documents.last else {
self.refreshControl.endRefreshing()
return
}
print(snapshot.documents)
self.lastDocumentSnapshot = lastSnap
snapshot.documentChanges.forEach({ (change) in
if change.type == .added {
let data = change.document.data()
let text = data["message"] as! String
let fromID = data["fromID"] as! String
let messageID = data["messageId"] as? String ?? ""
let isRead = data["isRead"] as? Bool ?? false
let timestamp = data["timestamp"] as! Timestamp
let user = MessageKitUser(senderId: fromID, displayName: "")
let message = MessageKitText(text: text, user: user, messageId: messageID, date: Date(), isRead: isRead, firDate: timestamp )
self.insertMessage(message)
self.refreshControl.endRefreshing()
}
})
}
}
When I use snapshot.documents.last nothing returns because im fetching the "last" documents initially. I need to get the 5 snapshots before the last, each time when paginating.
Let me know if this doesn't make sense and you have questions. Thank you!!
回答1:
Say you have 10 documents:
[1,2,3,4,5,6,7,8,9,10]
Your limitToLast(5) will retrieve:
[6,7,8,9,10]
Since you're using start(afterDocument:, Firestore starts after document 6, which is not what you want. Instead you want to to end(beforeDocument::
query = DBCall.fireRef.collection("friendMessages")
.document(currentUID)
.collection(friendUID)
.order(by: "timestamp")
.end(beforeDocument: nextStartingSnap)
.limit(toLast: 5)
I also reverse the limit(toLast: and end(beforeDocument:. It makes no difference to the results, but reads slightly easier to me - as it's pretty much how Firestore processes your query:
- It loads the index on
timestamp. - It cut off everything from
nextStartingSnaponwards. - It then returns the last 5 documents that remain in the result.
来源:https://stackoverflow.com/questions/63552271/get-older-snapshot-for-pagination-when-querying-with-limittolast