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

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

现有行为

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

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

需要考虑的几个问题:

  • Firestore get() 总是尝试首先从 SERVER 获取数据,即使我将 CACHE 添加到我的查询中,我怎么能只同步更新的文档
  • 在我的循环视图中,我希望数据按字段日期而不是lut(上次修改时间)排序
  • 使用FireStore Snapshot监听器,我无法查询如此大的记录集。

答案 1

Firestore get() 总是尝试首先从 SERVER 获取数据,即使我将 CACHE 添加到查询中,如何仅同步更新的文档?

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

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

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

另外根据关于Query的get()方法的官方文档:

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

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

如您所见,我们现在可以作为参数传递给 源 或 源,以便我们可以强制从 或 尝试服务器检索数据并回退到缓存。DocumentReferenceQueryserver 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

如果只想获取 ,则可以查看快照之间的更改。官方文档中的一个例子是: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;
            }
        }

        }
    });

是否查看每个特定情况的开关语句?第二种情况将帮助您仅获取更新的数据。

在我的循环视图中,我希望数据按字段日期而不是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);

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

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

哦,是的,你可以。根据这个答案,Firebase可以有效地循环遍历数十亿个物品。这个答案适用于Firebase实时数据库,但相同的原则也适用于Cloud Firestore。


答案 2

您只需添加要检索的数据源即可

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

推荐