Синхронизация областей с большой коллекцией в Firestore - архитектурные вопросы / проблемы - PullRequest
0 голосов
/ 08 января 2019

У меня есть коллекция объектов товара (title, desc, price, Quant, urlString и т. Д.) В коллекции Firestore. В настоящее время около 1000 предметов, но это может пойти до 10к. При запуске приложения для iOS я настраиваю прослушиватель коллекции (db.collection("products").rx.listen()), который затем сохраняет изменения в локальной базе данных Realm.

.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)

Я подробно ознакомился с документацией по пожарному магазину, но не уверен на 100%, что этот подход надежен или эффективен.

Вопрос: Когда приложение запустится, Firestore будет загружать все 10 тыс. Документов каждый раз, прежде чем описывать изменения? Или он будет кешировать все 10 Кб в первый раз, а затем загружать изменения только при последующих запусках. Я уверен, что после того, как событие изменения сработало, все последующие события будут получать только изменения в базе данных Firestore. Что меня беспокоит, так это первая подписка на слушателя, когда приложение запускается, оно загружает все 10 тыс. Элементов (что будет дорого).

РЕДАКТИРОВАТЬ 9 января 2019 г .:

В итоге я реализовал элегантный ответ @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)

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Когда приложение запустится, Firestore будет загружать все документы по 10 тыс. Каждый раз перед описанием изменений?

Когда вы прослушиваете изменения в Cloud Firestore для изменений в реальном времени, используя метод Firestore Query addSnapshotListener(), он:

Начинает прослушивание этого запроса.

Это означает, что при первом подключении слушателя вы получаете все документы, соответствующие этому конкретному запросу.

Или он будет кэшировать все 10 Кб в первый раз, а затем загружать изменения только при последующих запусках.

Поскольку в Firestore по умолчанию включено сохранение в автономном режиме, это означает, что после выполнения запроса результаты отслеживаются на устройстве пользователя. Кроме того, каждый раз, когда свойство в документе изменяется, вы получаете уведомление в соответствии с этим изменением. Очевидно, это происходит только в том случае, если слушатель остается активным и не удаляется. Поэтому, если ничего в базе данных не изменилось, вы получаете все данные из кэша.

Как и @zavtra, упомянутый в его ответе, вы можете добавить add под каждым объектом из вашей коллекции свойство Date ( это *1023*, как вы можете добавить его) и запрос ваша база данных на клиенте, согласно этому новому свойству, для всех документов, которые изменились с предыдущего раза.

Я также рекомендую посмотреть ответ Дуга Стивенсона из этого поста , для лучшего понимания.

0 голосов
/ 08 января 2019

По документам:

docChanges возвращает массив изменений документа с момента последнего снимок. Если это первый снимок, все документы будут в список как «добавленные» изменения.

Каждый раз, когда вы перезапускаете приложение, запускается это «первый снимок». Если вы хотите обойти это поведение, вам необходимо:

  1. Получить самый последний документ, сохраненный локально, с отметкой времени.
  2. Создание запроса, в котором все документы начинаются с этой отметки времени (т. Е. Отметка времени каждого документа минимальна, последняя сохраненная отметка времени)
  3. Подписаться на изменения этого запроса в записи приложения.

Для этого вам нужно будет добавить поле временной метки к каждому документу и правило indexOn в правилах вашего firestore к полю временной отметки, чтобы предотвратить загрузку и сортировку всей коллекции на стороне клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...