Firestore 查询再次读取所有文档(从数据库中),即使启用了持久性也只修改了一个 [英] Firestore query reads all the documents again (from database) when only one is modified even with persistence enabled

查看:13
本文介绍了Firestore 查询再次读取所有文档(从数据库中),即使启用了持久性也只修改了一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

预期行为:我假设当文档的某些字段被修改时,查询只会返回该文档,因此它只会被视为 1 次读取.假设我查询一个包含 n 个文档的集合,我希望它对初始状态进行 n 次读取,如果稍后修改文档,则只会从数据库中再次读取该文档,从而总共读取 n+1 次.

Expected Behavior: I assumed that when some field of a document is modified, query will only return that document and so it would be considered only 1 read. Say I query a collection with n documents, I would hope that it would be n reads for the initial state, and if a document is modified later only that document would be read again from database, resulting in n+1 reads in total.

我所见最初是 n 次读取,并且每当修改一个文档时 n 次读取 无论是否启用离线持久性;导致 2n 次读取所有fromCache : false"元数据.

What I see is n reads initially, and n reads later whenever one document is modified regardless of Offline Persistence being enalbed or not; resulting in 2n reads with all "fromCache : false" metadata.

  myCollection: 
         doc1 : 
              value: "some string"
         ...
         docn: 
             value: "some text" 

稍后我通过控制台更改一个文档的值:

later I change value for one document via console:

     myCollection: 
         doc1 : 
              value: "changed to other value"
         ...
         docn: 
             value: "some text" 

但是我在查询的快照中再次获得了所有 n 个文档.尽管我可以使用s.docChanges"观察更改,但快照似乎包含所有 n 个文档.

But I get all n documents again in the snapshot of query. Regardless of the fact that I can observe changes using "s.docChanges", it seems that snapshot has all the n documents.

  const someCollectionRef = firebase.firestore().collection("collection/document/subdocl‌​lection"); 
  someCollectionRef.onSnapshot(s => {

      var d = [];
      s.forEach(doc => {

           d.push(doc.data()));

           //fromCache is always false even when one document is 
           //modified it seems that all documents are read from db again 
           console.log(`metadata is ` , doc.metadata);  
      }
      //d seems to have all my documents even when only 1 is modified

  });

启用离线持久性没有区别.我测试了启用离线持久性的相同示例,没有区别!修改文档仍然会导致使用fromCache : false"元数据读取所有文档,即从数据库中读取它们.从缓存中读取数据的唯一时间是刷新查询但文档全部相同时.

No difference with offline persistence enabled. I tested the same example with offline persistence enabled and no difference! Modifying a document still causes all the documents to be read with "fromCache : false" metadata, i.e, they are read from database. The only time data is being read from cache is when a query is refreshed but documents are all identical.

推荐答案

我注意到了这种行为并做了一些研究:实际上一切都很好!

I noticed this behavior and did some research: actually all is well!

当您正在收听 N 个文档的集合时,您对初始状态执行 N 次读取,然后在文档更改时执行 1 次读取,正如预期的那样.这在 youtube 视频有关计费方面的文档.

When you are listening to a collection of N documents, you perform N reads for the initial state, then 1 read when a documents changes, as expected. This is described nicely in this youtube video, and in the documentation for the billing aspect.

陷阱是 fromCache 元数据.当您收到文档更改的更新时,所有其他未更改的文档都有 fromCache: false,但它们实际上来自缓存,正如 Firebase 开发人员在 这个答案

The trap is the fromCache metadata. When you receive an update for a document change, all the other unchanged documents have fromCache: false, but they actually come from the cache, as described by a Firebase dev in this SO answer!

fromCache 元数据仅在离线持久化范围内为真,当初始 N 次读取是从本地缓存完成时.当一个文档从服务器接收到数据时,它设置 fromCache: false,并且永远不会回到 fromCache: true.命名令人不安,但它似乎按预期工作.

The fromCache metadata is true only in the scope of offline persistence, when the initial N reads were done from the local cache. When a document has received data from the server, it sets fromCache: false, and never goes back to fromCache: true. The naming is disturbing, but it seems to be working as expected.

以及测试代码:

<html>
    <body>
        <script src="/__/firebase/7.22.1/firebase-app.js"></script>
        <script src="/__/firebase/7.23.0/firebase-firestore.js"></script>
        <script src="/__/firebase/init.js"></script>
        <script>
            firebase.firestore().enablePersistence().then(() => {
                    const collectionRef = firebase.firestore().collection("/fruits");
                    collectionRef.onSnapshot({includeMetadataChanges: true}, snapshot => {
                    console.log("=================== snapshot received ===================");
                    snapshot.forEach(doc => {
                        console.log(`doc ${doc.id}, metadata:`, doc.metadata);
                    });
                });
            });
        </script>
    </body>
</html>

我使用 Firebase 控制台修改了一个文档,在我浏览器的控制台中,当长轮询请求终止时,它显示单个文档已传输:

I modify a document using Firebase console, and in my browser's console, when the long polling request terminates, it shows that a single document was transferred:

15
[[14,["noop"]]]370
[[15,[{
  "documentChange": {
    "document": {
      "name": "projects/xxx/databases/(default)/documents/fruits/apricot",
      "fields": {
        "color": {
          "stringValue": "red"
        }
      },
      "createTime": "2020-10-13T08:14:19.649748Z",
      "updateTime": "2020-10-13T14:16:09.991161Z"
    },
    "targetIds": [
      2
    ]
  }
}
]]]122
[[16,[{
  "targetChange": {
    "resumeToken": "CgkI+bft8+Cx7AI=",
    "readTime": "2020-10-13T14:16:09.991161Z"
  }
}
]]]15
[[17,["noop"]]]

这篇关于Firestore 查询再次读取所有文档(从数据库中),即使启用了持久性也只修改了一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆