我正在将Firestore DB用于电子商务应用程序。我有一个产品集合,每个产品都有一个文档,其中有一个";标题";字段和";search_keywords";领域搜索关键字字段存储一个数组。例如,如果标题=";苹果";,则";search_keywords";字段将存储以下数组:["a"、"ap"、"app"、"appl"、"apple"]。当用户开始键入";苹果;在搜索框中,我想向用户显示所有产品中";search_keywords";包含";a";,则当他们键入";p〃;,我想显示所有搜索关键字包含"的产品;ap";。。。等等。以下是每次键入额外字母时调用的代码片段:
firebaseFireStore.collection("Produce").whereArrayContains("search_keywords", toSearch).get()
例如,在每种情况下,在每次连续调用(其中键入了额外的字母)时返回的文档都将是上一次调用中返回的文档的子集——它只是一个较小的文档列表——在上一次查询中读取的文档。我的问题是,由于在连续查询中检索的文档是在先前查询中检索到的文档的子集,我会根据每个连续查询返回的文档数量收取读取费用吗?还是Firestore会将它们放在缓存中并从那里读取,因为连续结果集是先前结果集的子集。这个问题在我脑海里已经有一段时间了,每次我寻找它时,似乎都找不到明确的答案。例如,根据我的研究,以下两篇关于Stackoverflow的帖子涉及类似的问题,以下是相关的引文,但它们似乎相互矛盾,因为@AlexMamo说"它将始终读取联机版本的文档。。。[在线时]";@Doug Stevenson说";如果在客户端上启用了本地持久性(默认情况下),并且文档尚未在服务器中更新。。。[它将从缓存中获取它们]";。如果有人知道答案的话,我希望对此做出任何澄清。谢谢
"如果OP启用了离线持久性,这在Cloud Firestore中是默认的,那么他将只能在离线时读取缓存。当OP具有互联网连接时,它将始终读取在线版本的文档"-Alex Mamo(https://stackoverflow.com/a/69320068/14556386)
"根据Doug Stevenson的回答,只有在服务器上执行读取时才会收费,而不是在本地缓存上。也就是说,如果在客户端上启用了本地持久性(默认情况下),并且文档尚未在服务器中更新"(https://stackoverflow.com/a/61381656/14556386)
EDIT:此外,如果对于Firestore搜索检索到的每个产品文档,我都会从Firebase Storage下载相应的图像文件。它会向我收取连续下载该文件的费用吗?还是会识别出我以前下载过该图像并自动从缓存中提取?
首先,将["a"、"ap"、"app"、"appl"、"apple"]存储到一个数组中并执行where ArrayContains()查询,听起来不是一个可行的想法。为什么?想象一下,你有一家拥有10万件产品的大型网店,其中5万件以";a";。你愿意每次用户键入";a";?这是一个非常昂贵的功能。
当用户键入两个甚至三个字符时,很可能应该返回相应的文档。你将大大降低成本。或者你可以考虑使用我在下面的文章中解释的解决方案:
- 如何更便宜地筛选Firestore数据
让我们继续前进。
例如,在每种情况下,在每次连续调用(其中键入了额外的字母)时返回的文档都将是上一次调用中返回的文档的子集,它只是一个较小的文档列表。
是的,没错。
我的问题是,由于在连续查询中检索到的文档是在先前查询中检索的文档的子集,是否会根据每个连续查询返回的文档数量向我收取读取费用?
是。您将始终被收取与查询返回的文档数相等的读取次数。查询以前是否执行过并不重要。每次执行新查询时,您将被收取与您获得的文档数相等的读取次数。
例如,假设您执行以下查询:
.whereArrayContains("search_keywords", "a")
然后您得到100个文档,然后执行:
.whereArrayContains("search_keywords", "ap")
如果你只得到30个文档,你必须支付130次阅读费用,而不是只有100次。因此,第二个查询返回的文档是否是第一个查询返回文档的子集并不重要。
或者Firestore会把它们放在缓存中并从那里读取它们,因为连续的结果集是先前结果集的子集。
不,不会。只有当用户失去互联网连接时,它才会从缓存中读取这些文档,否则它将始终读取Firebase服务器上存在的文档的在线版本。只有当用户处于脱机状态时,文档的缓存版本才能工作。我还写了一篇关于这个主题的文章,名为:
- 在Firestore中没有更改文档的情况下,如何大幅减少读取次数
在Doug的回答中:
- 每次更改位置时,我是否要负责读取操作
他清楚地说:
每次调用get()时,都会根据服务器上读取的文档数收取费用。
因此,如果调用get(),则必须按读取量(返回的文档数)付费。
以下声明可用:
如果在客户端中启用了本地持久性(默认情况下),那么如果文档在服务器上也没有更改,则文档可能来自缓存。
当您正在收听实时更新时。根据文件:
当您收听查询结果时,每次添加或更新结果集中的文档时,都会收取读取费用。当文档由于更改而从结果集中删除时,您还将收取读取费用。
我想补充一点,如果一切都没有改变,你就不必支付任何费用。同样,根据相同的文档:
此外,如果侦听器断开连接超过30分钟(例如,如果用户离线),您将被收取读取费用,就像您发出了一个全新的查询一样。
因此,如果侦听器处于活动状态,则始终从缓存中读取文档。请记住,get()操作与监听实时更新不同。
如果对于Firestore搜索检索到的每个产品文档,我从Firebase Storage下载其相应的图像文件。它会向我收取连续下载该文件的费用吗?还是会识别出我以前下载过该图像并自动从缓存中提取?
如果您一次又一次地下载图像,您将始终被收取费用,除非您使用的库可以帮助您缓存图像。对于Android,有一个名为Glide的库:
Glide是一个适用于Android的快速高效的开源媒体管理和图像加载框架,它将媒体解码、内存和磁盘缓存以及资源池封装到一个简单易用的界面中。