我在 Firestore 集合中有一个产品对象集合(标题、描述、价格、定量、urlString 等)。目前大约有 1000 件商品,但可能会达到 10k。在我的 iOS 应用程序启动时,我设置了一个集合侦听器(db.collection("products").rx.listen()
)然后将更改保存到本地领域数据库。
.subscribe(onNext: { querySnapshot in
querySnapshot.documentChanges.forEach { docChange in
autoreleasepool {
let realm = try! Realm(configuration: Realm.Configuration.defaultConfiguration)
let newData = docChange.document.data()
if let item = itemFactory.createItem(using: newData) {
if (docChange.type == .added) {
//realm.add(item)
}
if (docChange.type == .modified) {
//realm.update(item)
}
if (docChange.type == .removed) {
//realm.delete(item)
}
}
}
}
}, onError: { error in
print("Error fetching snapshots: \(error)")
}).disposed(by: disposeBag)
我已经详细阅读了 firestore 文档,但我不是 100% 相信这种方法是可靠的或高性能的。
问题:当应用程序启动时,Firestore 每次都会下载所有 10k 文档,然后再描述更改吗?或者它会在第一次缓存所有 10k,然后仅在后续启动时下载更改。我确信一旦更改事件触发,所有后续事件将仅获取对 Firestore 数据库的更改。我担心的是,当应用程序启动时首次订阅侦听器,它会下载所有 10k 项(这将是昂贵的)。
2019 年 1 月 9 日编辑:
我最终实现了 @zavtra 优雅的答案,代码大致如下:
var newestUpdatedAt = UserDefaults.standard.double(forKey: kUDItemUpdatedAt)
//...
db.collection(kProducts)
.whereField(kUpdatedAt, isGreaterThan: newestUpdatedAt)
.rx.listen()
//...
querySnapshot.documentChanges.forEach { docChange in
autoreleasepool {
let realm = try! Realm(configuration: Realm.Configuration.defaultConfiguration)
let newData = docChange.document.data()
if let item = itemFactory.createItem(using: newData) {
if item.updatedAt > newestUpdatedAt {
newestUpdatedAt = item.updatedAt
}
if (docChange.type == .added) {
//realm.add(item)
}
if (docChange.type == .modified) {
//realm.update(item)
}
if (docChange.type == .removed) {
//realm.delete(item)
}
}
}
}
UserDefaults.standard.set(newestUpdatedAt, forKey: kUDItemUpdatedAt)
根据文档:
docChanges 返回自上次以来文档更改的数组
快照。如果这是第一个快照,则所有文档都将位于
列为“添加”更改。
每次重新启动应用程序都会触发此“第一个快照”行为。如果您想解决此行为,您必须:
- 检索本地保存的最新文档及其时间戳。
- 构建一个查询,其中所有文档都从该时间戳开始(即每个文档的时间戳至少是最近保存的时间戳)
- 订阅应用程序条目上该查询的更改。
为此,您必须向每个文档添加一个时间戳字段,并在时间戳字段上的 firestore 规则中添加一个“indexOn”规则,以防止客户端下载和排序整个集合。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)