如何避免使用缓存进行不必要的 Firestore 读取



>我有一个按日期排序的行程数据列表(大型集合(。

现有行为

我将所有行程数据存储到 SqlLite DB 中。对于添加的每个新数据,我曾经收到 fcm 通知,并且我仅使用上次更新时间概念同步新添加的数据。这样,当 cx 打开应用程序时,他将始终从我的数据库中读取数据,从而节省读取网络操作。

我怎样才能用Firestore实现同样的目标?

需要考虑的几个问题:

  • Firestore get(( 总是尝试首先从服务器获取数据,即使我将缓存添加到我的查询中,我如何只同步更新的文档
  • 在我的回收器视图中,我希望数据按字段日期排序,而不是按 lut(上次修改时间(
  • 使用FireStore Snapshot Listener,我无法查询如此大的记录集。

Firestore get(( 总是尝试首先从服务器获取数据,即使我将缓存添加到我的查询中,我如何只同步更新的文档?

根据有关启用离线数据的官方文档:

对于 Android 和 iOS,默认情况下启用离线持久性。

因此,要使用离线持久性,您无需对代码进行("添加"(任何更改即可使用和访问 Cloud Firestore 数据。

同样根据有关 Query 的 get(( 方法的官方文档:

默认情况下,get(( 会尝试通过等待来自服务器的数据来尽可能提供最新数据,但如果脱机且无法访问服务器,它可能会返回缓存数据或失败。可以通过源参数更改此行为。

所以这是正常行为。从 2018-06-13 (16.0.0 SDK( 开始,现在可以指定我们要从中获取数据的源。我们可以借助 DocumentReference.get(Source source( 和 Query.get(Source source( 方法来实现这一点。

如您所见,我们现在可以作为参数传递给DocumentReference或源Query,以便我们可以强制从server onlycache only或尝试服务器检索数据并回退到缓存。

所以这样的事情现在是可能的:

yourDocRef.get(Source.SERVER).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
//Get data from the documentSnapshot object
}
});

在这种情况下,我们强制仅从服务器检索数据。如果要强制仅从缓存中检索数据,则应作为参数传递给get()方法Source.CACHE.更多信息请点击此处。我还写了一篇文章,可以帮助理解更清晰的概念:

  • 如何在Firestore中没有更改文档时大幅减少读取次数?

如果只想获取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 语句?第二种情况将帮助您仅获取更新的数据。

在我的回收器视图中,我希望数据按字段日期排序,而不是按 lut(上次修改时间(

在这种情况下,您应该创建一个查询,允许您按特定日期属性对结果进行排序。假设您有一个如下所示的数据库结构:

Firestore-root
|
--- items (collection)
|
--- itemId (document)
|
--- date: Oct 08, 2018 at 6:16:58 PM UTC+3
|
--- //other properties

类似的查询将帮助您实现此目的:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionRefference itemsRef = rootRef.collection("items");
Query query = itemsRef.orderBy("date", Query.Direction.ASCENDING);

这也是向云 Firestore 数据库添加时间戳的推荐方法。

使用FireStore Snapshot Listener,我无法查询如此大的记录集。

哦,是的,你可以。根据这个答案,Firebase可以有效地循环处理数十亿个项目。这个答案适用于Firebase实时数据库,但同样的原则也适用于Cloud Firestore。

您可以添加要检索的数据源

firestore.collection("yourCollection").get({source:"cache"})

我认为在这种情况下您应该使用此软件包: firestore_cache

使用它的唯一方法是在要从中获取数据的集合中再添加一个名为"status"的文档。例如,您想从用户集合中获取数据,那么您需要添加文档"status"["User/status"],其中包含一个字段:"updateAt"和值,其编写方式如下:

updatedAt: admin.firestore.FieldValue.serverTimestamp()

因此,每次我们要添加,更新或删除当前集合中的数据时,都必须更新上面的字段。否则,你的应用不会自动更新数据。很好地阅读了文档。

最新更新