I have a collection of product objects (title, desc, price, quant, urlString, etc) in a Firestore collection. Currently around 1000 items, but that could go to 10k. On my iOS app launch, I setup a collection listener (db.collection("products").rx.listen()
) which then saves changes to a local Realm database.
.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)
I've read the firestore docs in detail but I'm not 100% confident this approach is reliable or performant.
Question: When the app launches, will Firestore download all 10k documents each time, before describing the changes? Or will it cache all 10k the very first time then only download changes on subsequent launches. I'm confident once a change event has fired, all subsequent events will only pick up changes to the Firestore database. What I'm concerned about is on first subscribing to the listener when the app launches, it downloads all 10k items (which would be costly).
EDIT 9 Jan 2019:
I ended up implementing @zavtra elegant answer with code roughly looking like this:
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)