Firestore 查询再次读取所有文档(从数据库中),即使启用了持久性也只修改了一个 [英] Firestore query reads all the documents again (from database) when only one is modified even with persistence enabled
问题描述
预期行为:我假设当文档的某些字段被修改时,查询只会返回该文档,因此它只会被视为 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/subdocllection");
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屋!