【问题标题】:How to avoid unnecessary Firestore reads with Cache如何避免使用缓存进行不必要的 Firestore 读取
【发布时间】:2019-03-13 00:41:53
【问题描述】:

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

现有行为

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

如何使用 Firestore 实现相同的目标?

需要考虑的几个问题:

  • Firestore get() 总是尝试首先从 SERVER 获取数据,即使我将 CACHE 添加到我的查询中,我如何才能只同步更新的文档
  • 在我的 Recyler 视图中,我希望数据按字段 date 而不是 lut(last-modified-time)
  • 排序
  • 使用 FireStore 快照侦听器,我无法查询如此大的记录集。

【问题讨论】:

    标签: java android firebase google-cloud-firestore firebaseui


    【解决方案1】:

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

    根据enable offline data的官方文档:

    对于 Android 和 iOS,默认启用离线持久化。

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

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

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

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

    如您所见,我们现在可以将参数作为参数传递给DocumentReferenceQuery 源,这样我们就可以强制从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。更多信息here。我还写了一篇文章,可以帮助理解更清晰的概念:

    如果你只想得到updated documents,你可以view changes between snapshots。官方文档中的一个例子是:

    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(last-modified-time)

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

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

    This 也是一种向 Cloud Firestore 数据库添加时间戳的推荐方式。

    使用 FireStore 快照侦听器,我无法查询如此大的记录集。

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

    【讨论】:

    • 谢谢 Alex,我不知道 Snapshot Listener 可以用于大型记录,为什么 FirebaseUI-Firestore 不支持分页时的实时更新?您的解决方案是否建议仅将 SnapshopListener 用于我的用例,但如果用户离线 30 分钟或说退出应用程序等,SnapListener 将再次读取整个数据。----根据您的说法,什么是最好的通过最小化读取(成本)操作来在回收站视图中提供大型文档的方法?
    • "为什么 FirebaseUI-Firestore 不支持分页时的实时更新?"你应该为此问另一个问题。同时,this 是一种推荐的方式,您可以通过将查询游标与 limit() 方法相结合来对查询进行分页。我还建议您看看这个 video 以便更好地理解。
    • 如果您需要实时获取数据,可以使用SnapshopListener,否则只需使用get() 调用。 Firestore 默认启用离线持久性。因此,一旦您重新上线,您就会从 Firebase 服务器获得所有更新。最好的解决方案?绝对是分页!
    【解决方案2】:

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

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

    【讨论】:

    • 能否补充说明
    猜你喜欢
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 2020-07-02
    • 1970-01-01
    相关资源
    最近更新 更多