Как избежать ненужных операций чтения Firestore с кэшем
У меня есть список данных trips (большие наборы), упорядоченных по дате.
Существующее поведение
Я сохраняю все данные trips в базе данных SQLLite. Для каждого добавления новых данных я получал уведомление fcm и синхронизировал только новые добавленные данные, используя концепцию времени последнего обновления. Таким образом, когда cx открывает приложение, он всегда будет считывать данные из моей базы данных, следовательно, сохраняя операции чтения и сети.
Как я мог бы добиться того же с Firestore?
Несколько проблем, которые следует учитывать:
- Firestore get () всегда пытается сначала получить данные с сервера, даже если я добавляю КЭШ к своему запросу, как я могу синхронизировать только обновленный документ
- В моем представлении Recyler я хочу, чтобы данные были упорядочены по полю дата, а не по lut (время последнего изменения)
- С помощью FireStore Snapshot Listener я не могу запросить такой большой набор записей.
Переведено автоматически
Ответ 1
Firestore get() всегда пытается сначала получить данные с сервера, даже если я добавляю КЭШ к своему запросу, как я могу синхронизировать только обновленный документ?
Согласно официальной документации, касающейся включения автономных данных:
Для Android и iOS автономное сохранение включено по умолчанию.
Итак, чтобы использовать автономную сохраняемость, вам не нужно вносить ("добавлять") какие-либо изменения в свой код, чтобы иметь возможность использовать облачные данные Firestore и получать к ним доступ.
Также согласно официальной документации, касающейся метода get() запроса:
По умолчанию get() пытается предоставить актуальные данные, когда это возможно, ожидая данных от сервера, но это может вернуть кэшированные данные или завершиться сбоем, если вы находитесь в автономном режиме и до сервера невозможно дозвониться. Это поведение можно изменить с помощью параметра Source.
Итак, это нормальное поведение. Начиная с 2018-06-13 (16.0.0 SDK) теперь можно указать источник, из которого мы хотим получить данные. Мы можем достичь этого с помощью методов DocumentReference.get(исходный код) и Query.get (исходный код).
Как вы можете видеть, теперь мы можем передавать в качестве аргумента в DocumentReference
или в Query
источник, чтобы мы могли принудительно извлечь данные с server only
, cache only
или попытаться выполнить сервер и вернуться к кэшу.
Итак, теперь возможно что-то подобное:
yourDocRef.get(Source.SERVER).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
//Get data from the documentSnapshot object
}
});
В этом случае мы принудительно извлекаем данные только с сервера. Если вы хотите принудительно извлекать данные только из кэша, вам следует передать в качестве аргумента get()
методу, Source.CACHE
. Больше информации здесь. Я также написал статью, которая может помочь более четко понять концепцию:
Если вы хотите получить только updated documents
, вы можете просмотреть изменения между снимками. Примером из официальной документации может быть:
db.collection("cities")
.whereEqualTo("state", "CA")
.addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot snapshots,
@Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.w(TAG, "listen:error", e);
return;
}
for (DocumentChange dc : snapshots.getDocumentChanges()) {
switch (dc.getType()) {
case ADDED:
Log.d(TAG, "New city: " + dc.getDocument().getData());
break;
case MODIFIED:
Log.d(TAG, "Modified city: " + dc.getDocument().getData());
break;
case REMOVED:
Log.d(TAG, "Removed city: " + dc.getDocument().getData());
break;
}
}
}
});
Смотрите инструкцию switch для каждого конкретного случая? Второй случай поможет вам получить только обновленные данные.
В моем представлении Recyler я хочу, чтобы данные были упорядочены по дате поля, а не по lut (время последнего изменения)
В этом случае вам следует создать запрос, позволяющий упорядочивать результаты по определенному свойству date . Предполагая, что у вас есть структура базы данных, которая выглядит следующим образом:
Firestore-root
|
--- items (collection)
|
--- itemId (document)
|
--- date: Oct 08, 2018 at 6:16:58 PM UTC+3
|
--- //other properties
Запрос like поможет вам достичь этого:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionRefference itemsRef = rootRef.collection("items");
Query query = itemsRef.orderBy("date", Query.Direction.ASCENDING);
Это также рекомендуемый способ добавления временной метки в облачную базу данных Firestore.
С помощью FireStore Snapshot Listener я не могу запросить такой большой набор записей.
О, да, вы можете. Согласно этому ответу, Firebase может эффективно перебирать миллиарды элементов. Этот ответ предназначен для базы данных Firebase в реальном времени, но те же принципы применимы и к облачному Firestore.
Ответ 2
вы можете просто добавить источник данных, которые будут восстановлены
Ответ 3
Я думаю, вам следует использовать этот пакет для этого случая: firestore_cache
Единственный способ использовать это - добавить еще один документ с именем "status" внутри коллекции, из которой вы хотите получить данные. Например, вы хотите получить данные из коллекции пользователей, тогда вам нужно добавить документ "status" ["Пользователь / статус"] с полем: "updatedAt" и значением, которое записывается следующим образом:
updatedAt: admin.firestore.FieldValue.serverTimestamp()
Поэтому каждый раз, когда мы хотим добавить, обновить или удалить данные в текущей коллекции, мы должны обновлять это поле выше. В противном случае ваше приложение не будет обновлять данные автоматически. Внимательно прочитайте документацию.