如何减少Firestore集合中的读取次数?

时间:2019-09-11 12:09:28

标签: java android firebase google-cloud-firestore

我已经从我的上一个问题中学到了如何使用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次甚至更多。

到目前为止,我的应用程序运行良好,但我认为对于一个简单的字典应用程序来说,它的成本很高。如何减少大量读取?

2 个答案:

答案 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.

示例:

  1. 用户类型B:启动计时器0.3秒。
  2. 用户类型r在0.2秒后:取消计时器,在0.3秒内启动一个新计时器。
  3. 用户类型o在0.1秒后:取消计时器,在0.3秒内启动一个新计时器。
  4. 0.3秒过去了,没有打字。从文本Bro开始搜索。