Java 如何减少Firestore集合中的读取次数?
我从前面的一个问题中学到了如何使用,并在我的海事术语词典应用程序中实现了它。数据库中有很多术语 db是这样的:Java 如何减少Firestore集合中的读取次数?,java,android,firebase,google-cloud-firestore,Java,Android,Firebase,Google Cloud Firestore,我从前面的一个问题中学到了如何使用,并在我的海事术语词典应用程序中实现了它。数据库中有很多术语 db是这样的: maritime_terms |- id |- term: "broad reach" |- details: "Sailing with the wind abaft the beam." |- etc 与我使用的文档一样: db.collection("maritime_terms") .startAt(searchText
maritime_terms
|- id
|- term: "broad reach"
|- details: "Sailing with the wind abaft the beam."
|- etc
与我使用的文档一样:
db.collection("maritime_terms")
.startAt(searchText)
.endAt(searchText+ "\uf8ff")
.limit(20);
当我开始搜索例如“broad reach”并键入第一个字母b
,我得到20个结果。当我输入第二个字母时,我得到另外20个结果。等等问题是,我键入的每个字母都有20次读取,因此,对于一个简单的搜索,我从最少100次读取到150次甚至更多
到目前为止,我的应用程序工作得很好,但我认为一个简单的字典应用程序很昂贵。如何减少如此大量的读取?实现这一点的方法是
debounce
搜索
这意味着您可以利用这样一个事实,即用户将以每秒一定的按键次数键入,并在每次按键后将搜索延迟一小段时间
因此,例如,如果可以预期用户以每秒5次按键的速度键入,那么在每次按键后启动一个计时器,比如说0.3秒,只有在该计时器过期后才会启动搜索
如果用户在不到0.3秒的时间内轻触另一个键,则废弃计时器并再次启动计时器0.3秒
这样,只有当用户停止键入(或者至少现在停止键入)时,搜索才会使用整个字符串执行
然而,这并不是Firestore的变化。这将改变您的客户机逻辑
示例:
B
:启动计时器0.3秒r
0.2秒后:取消计时器,启动新计时器0.3秒o
0.1秒后:取消计时器,启动新计时器0.3秒Bro
开始搜索执行此操作的方法是对搜索进行
debounce
这意味着您可以利用这样一个事实,即用户将以每秒一定的按键次数键入,并在每次按键后将搜索延迟一小段时间
因此,例如,如果可以预期用户以每秒5次按键的速度键入,那么在每次按键后启动一个计时器,比如说0.3秒,只有在该计时器过期后才会启动搜索
如果用户在不到0.3秒的时间内轻触另一个键,则废弃计时器并再次启动计时器0.3秒
这样,只有当用户停止键入(或者至少现在停止键入)时,搜索才会使用整个字符串执行
然而,这并不是Firestore的变化。这将改变您的客户机逻辑
示例:
B
:启动计时器0.3秒r
0.2秒后:取消计时器,启动新计时器0.3秒o
0.1秒后:取消计时器,启动新计时器0.3秒Bro
开始搜索虽然Fogmeister的答案可以帮助您显著减少读取次数,但我将尝试提供另一种方法,但这将意味着您的数据库结构发生变化。这就是我要做的 首先,我将不再像您那样搜索
maritical\u terms
集合。相反,我将创建一个包含数据库中所有术语的文档。每个术语都将添加到术语数组中。根据条款的长度,可以在一份文件中包含所有条款。我这样说是因为文件有限制。因此,当涉及到可以将多少数据放入文档时,存在一些限制。根据官方文件,关于:
文档的最大大小:1 MiB(1048576字节)
如您所见,单个文档中的数据总量限制为1 MiB。当我们谈论存储文本时,您可以存储很多
如果所有术语都不适合单个文档,那么您只需为字母表中的每个字母创建一个文档即可。由于您知道搜索内容,因此很容易知道要阅读的文档。因此,请看一下以下模式:
Firestore-root
|
--- alphabetTerms (collection)
|
--- a (document)
| |
| --- aTerms: ["A-Term", "A-Term", "A-Term"]
|
--- b (document)
|
--- bTerms: ["B-Term", "B-Term", "B-Term"]
要获取a
文档,只需获取一个引用并进行get()
调用:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
DocumentReference aRef = rootRef.collection("alphabetTerms").document("a");
aRef.get().addOnCompleteListener(/* ... */);
即使aTerms
是一个数组,当您进行get()
调用时,也会将其作为列表
和而不是作为数组。然后,您只需使用以下命令搜索该字符串列表:
termFromTheList.contains(searchedTerm);
需要注意的一点是,为了使用此解决方案,所有术语都必须是唯一的
此解决方案比您现在使用的解决方案要好得多,因为它允许您搜索子字符串。例如,如果您想在broad reach
中搜索reach
,这是不可能的,除非您使用的是第三方服务,如
找到匹配项后,获取它并创建新查询:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference maritimeTermsRef = rootRef.collection("maritime_terms");
Query searchQuery = maritimeTermsRef.whereEqualTo("term", searchedTerm);
searchQuery.get().addOnCompleteListener(/* ... */);
使用上述解决方案,您将只读取一个文档来查找文档中的术语,并读取一个文档来显示术语的详细信息
因此,您将把读取次数从150次减少到仅2次
虽然Fogmeister的答案可以帮助您显著减少读取次数,但我将尝试提供另一种方法,但这将意味着您的数据库结构发生变化。这就是我要做的 首先,我将不再像您那样搜索
maritical\u terms
集合。相反,我将创建一个包含数据库中所有术语的文档。每个术语都将添加到术语数组中。根据条款的长度,可以在一份文件中包含所有条款