我已经从我的上一个问题中学到了如何使用pagination,并且已经在我的海事词典应用中实现了它。数据库中有很多术语。
数据库是这样的:
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);
当我开始搜索“广泛覆盖”时,输入第一个字母b
时,我会得到20条结果。当我输入第二个字母时,我会得到另外20个结果。等等。问题在于,我输入的每个字母都会获得20次阅读,因此,对于简单的搜索,我的阅读次数至少从100次增加到150次甚至更多。
到目前为止,我的应用程序运行良好,但我认为对于一个简单的字典应用程序来说,它的成本很高。如何减少大量读取?
答案 0 :(得分:4)
尽管Fogmeister的答案可以帮助您显着减少读取次数,但我将尝试为您提供另一种方法,但这将意味着您的数据库结构发生了变化。所以这就是我要做的。
首先,我将停止按照您的方式搜索maritime_terms
集合。取而代之的是,我将创建一个文档,其中包含您在数据库中拥有的所有术语。每个术语都会添加到一系列术语中。根据条款的长度,所有条款都可以放入一个文档中。我说这是因为文件有限制。因此,在文档中可以放入多少数据方面存在一些限制。根据有关usage and limits的官方文档:
文档的最大大小:1 MiB(1,048,576字节)
如您所见,单个文档中的数据总数限制为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()
调用时,也会以List<String>
的形式得到它,而不是的是数组。然后,您可以使用以下命令简单地搜索该字符串列表:
termFromTheList.contains(searchedTerm);
要注意的一件事是,所有术语都必须唯一才能使用此解决方案。
此解决方案比您现在使用的解决方案好得多,因为它允许您搜索子字符串。例如,如果您想在broad reach
中搜索reach
,除非您使用的是Algolia之类的第三方服务,否则这是不可能的。
找到匹配项后,获取并创建一个新查询:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference maritimeTermsRef = rootRef.collection("maritime_terms");
Query searchQuery = maritimeTermsRef.whereEqualTo("term", searchedTerm);
searchQuery.get().addOnCompleteListener(/* ... */);
使用上述解决方案,您最终将只阅读一份文档以找到文档中的术语,而阅读一份文档以显示术语的详细信息。
因此,您可以将读取次数从
150减少到 2 。
答案 1 :(得分:3)
执行此操作的方法是debounce
搜索。
这意味着您可以利用这样的事实,即用户将以每秒一定数量的按键数进行键入,并在每次按键后不久延迟搜索。
因此,例如,如果可以期望用户以每秒5次击键的速度键入内容,则在每次击键之后启动一个计时器(例如0.3秒),只有在该计时器到期后才开始搜索。 / p>
如果用户在不到0.3秒的时间内敲击另一个键,则取消计时器,然后再次启动计时器0.3秒。
这样,只有在用户停止键入(或至少现在暂时停止键入)后,搜索才会真正使用整个字符串执行。
但是,这不是Firestore中的更改。这将是您客户逻辑的改变。
You can read more about debouncing (and also throttling) at this link.
示例:
B
:启动计时器0.3秒。r
在0.2秒后:取消计时器,在0.3秒内启动一个新计时器。o
在0.1秒后:取消计时器,在0.3秒内启动一个新计时器。Bro
开始搜索。