Firestore分页获取下一批数据



我有这个函数,它从集合中获取文档。我从Firestore文档中得到了这个逻辑,但我不理解addSnapshotListener的用途。

在一个真实的场景中,我需要:

首先运行第一个查询,获取最后一个文档并将其传递给下一个查询,依此类推,对吗?这意味着在每次查询之后,我还需要返回最后一个文档?如果是这种情况,为什么我需要addSnapshotListener?我也可以从.getDocuments()获得lastSnapshot

class HomeViewModel: ObservableObject, LoadProtocol {
var firestoreService: FirestoreService = FirestoreService()
@Published var items: [Item] = []

let first: Query = Firestore.firestore().collection("items").limit(to: 1)
var next: Query = Firestore.firestore().collection("items").limit(to: 1)

init() {
self.first.addSnapshotListener { (snapshot, error) in

guard let snapshot = snapshot else {
print("Error retrieving cities: (error.debugDescription)")
return
}
guard let lastSnapshot = snapshot.documents.last else {
// The collection is empty.
return
}
// Construct a new query starting after this document,
// retrieving the next 25 cities.
self.next = self.firestoreService.db.collection("items")
.start(afterDocument: lastSnapshot)
// Use the query for pagination.

}
}

func refresh() {
self.firestoreService.fetchCollection(query: self.next) { (result: Result<[Item], Error>) in
switch result {
case .success(let items):
self.items += items
self.addToCategories()
case .failure(let error):
print(error)
}
}
}
}

问题是在实现中混合了基本游标分页和查询游标分页。

代码的基本游标分页部分(直到first.addSnapshotListener(是正确的,每次调用函数并解析它时都会执行,并将越来越多的数据返回到映射中,但查询游标分页部分永远不会被调用,因此您可以从实现中完全删除该部分。

所以你的代码应该看起来像:

func fetchCollection<Collection: CollectionProtocol>(lastSnapshot: DocumentSnapshot?, query: Query, completion: @escaping (Result<[Collection], Error>) -> Void) {
var first = query.limit(to: 1)
if let lastSnapshot = lastSnapshot {
first = query.start(afterDocument: lastSnapshot)
}
first.getDocuments() { (querySnapshot, error) in
if let snapshot = querySnapshot {
// print(snapshot.metadata.isFromCache)
completion(.success(snapshot.documents.map { document -> Collection in
return Collection(document: document)
}))
} else if let error = error {
completion(.failure(error))
}
}
}

注意:您也可以将.limit(to:1)添加到上次快照检查中,因为按照现在的方式,它将检索所有文档,当然,如果这是您想要的逻辑,请忽略此注意。


编辑:

如果你想使用查询光标分页,你可以按照这个例子,侦听器位于fetchCollection函数之外,每次触发getDocuments((并装载要执行的新查询时都会执行它:

//initial state of your app
var results = "nil";
//initial query
var query = db.collection("foo").document("bar").limit(to: 1);
//everytime you need more data fetched and on database updates to your snapshot this will be triggered
query.addSnapshotListener { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: (error!)")
return
}
snapshot.documentChanges.forEach { 
// update data
}
let next = db.collection("foo").document("bar").start(afterDocument: result.last!).limit(to: 1);
query = next;
};
//initial load of data
fetchCollection();
//simply executes the query
func fetchCollection() {
query.getDocuments { (document, error) in
if let document = document, document.exists {
if(result == "nil"){
result = document.data().map();
}else{
result.map({ document.data() })
}
} else {
print("Document does not exist")
}
}
}

注意:请记住,这是一个未经测试的示例,但它可能是您在应用程序中所需内容的一个很好的起点。此外,我使用此文档对侦听器进行实时更新,您可能会在该链接上找到更多信息。

相关内容

  • 没有找到相关文章

最新更新