首页 文章

如何删除firestore自动生成的单字段索引?

提问于
浏览
7

update: TLDR;
如果你到达这里,你应该重新检查你构建数据库的方式 . 您的文档可能会随着时间的推移而消耗(由于嵌套列表等) .

Original question:
我有一组包含很多字段的文档 . 即使没有简单的查询,我也不查询文件 - 我只使用 -

db.collection("mycollection").doc(docName).get().then(....);

为了阅读文档,所以我不需要为此集合编制任何索引 .

问题是firestore会自动生成单字段索引,并且由于字段数量导致限制超出索引:
enter image description here
如果我尝试向其中一个文档添加字段,则会抛出错误:

Uncaught (in promise) Error: Too many indexed properties for entity: app: "s~myapp",path <  Element {    type: "tags",    name: "aaaa"  }>
    at new FirestoreError (index.cjs.js:346)
    at index.cjs.js:6058
    at W.<anonymous> (index.cjs.js:6003)
    at Ab (index.js:23)
    at W.g.dispatchEvent (index.js:21)
    at Re.Ca (index.js:98)
    at ye.g.Oa (index.js:86)
    at dd (index.js:42)
    at ed (index.js:39)
    at ad (index.js:37)

我找不到任何方法来删除这些单字段索引或告诉firestore停止生成它们 . 我在firestore控制台中找到了这个:
enter image description here

但是没有办法禁用它,并禁用特定集合的自动索引 . 有办法吗?

4 回答

  • 2

    如Firestore文档中所述:

    Cloud Firestore需要为每个查询提供索引,以确保最佳性能 . 所有文档字段都自动编入索引,因此仅使用相等子句的查询不需要其他索引 . 如果尝试使用未映射到现有索引的range子句的复合查询,则会收到错误 . 该错误消息包含一个直接链接,用于在Firebase控制台中创建缺失的索引 .

    Can you update your question with the structure data you are trying to save?

    您的问题的解决方法是创建复合索引,或者作为最后一个资源,Firestore可能不适合您的应用程序的需求,Firebase Realtime Database可以是更好的解决方案 .

    见权衡:RTDB vs Firestore

  • 2

    您可以在Firestore firestore中删除简单索引 .

    如果在选择firestore数据库之后进入Indexes然后选择“single”索引,则会有一个Add Exemption按钮,允许您指定Collection(或Sub-collection)中哪些字段具有Firestore生成的简单索引 . 您必须指定集合后跟字段 . 然后,您可以单独指定每个字段,因为您无法指定整个集合 . 似乎没有检查有效的集合或字段名称 .

    我能想到检查这个的唯一方法是使用该字段进行查询,它应该失败 .

    我在大字符串字段中执行此操作,其中包含正常文本,因为它们需要很长时间才能编制索引,我知道我永远不会使用此字段进行搜索 .

    Firestore为每个简单字段(升序和降序)创建两个索引,但是如果您永远不需要第二个有助于提高性能并且不太可能达到索引限制,那么也可以创建一个删除其中一个的豁免 . 此外,您可以选择是否索引数组 . 如果你创建了一个数组的大量条目,那么这可以非常快地达到firestore对索引数量的限制,因此在使用索引时必须小心谨慎,因此设计师通常最好从索引中取出索引可能无法控制添加了多少数组数据项,结果达到了最大索引限制,并且应用程序将在原始海报解释时收到错误 .

    如果您不使用它们,也可以删除任何简单索引,即使复杂索引中包含字段也是如此 . 复杂的索引仍然有效 .

    其他值得关注的事情 .

    如果要索引时间戳字段(或在文档之间按顺序增加或减少的任何字段)并且您没有使用它来强制查询中的序列,则集合的最大写入速率为每秒500次写入 . 在这种情况下,可以通过删除增加和减少的索引来消除此限制 .

    请注意,与实时数据库不同,使用Auto-ID创建的字段不保证任何排序,因为它们由firestore生成以传播写入并避免热点或瓶颈,其中所有写入(因此读取)最终都在一个位置 . 这意味着通常需要时间戳来生成排序,但您可以设计集合/子集合数据布局以避免需要时间戳 . 例如,如果您使用时间戳来查找添加到集合的最后一个文档,则最好只存储添加的最后一个文档的ID .

    大型数组或映射字段也可以导致达到每个文档限制20,000个索引条目,因此您可以免除索引的数组(请参见下面的屏幕截图) .

    enter image description here

    一旦你添加了一个豁免,那么你将获得这个屏幕 .
    Exemption screen once one has been added

    也可以看到这个链接 .

    https://firebase.google.com/docs/firestore/query-data/index-overview

  • 0

    简短的回答是你现在不能用Firebase做到这一点 . 但是,这是一个很好的信号,您需要重构数据库模型以避免达到限制,例如每个文档1MB .

    文档讨论了数据的限制:

    您无法在嵌套列表上运行查询 . 此外,这不像其他选项那样可扩展,特别是如果您的数据随着时间的推移而扩展 . 随着列表越来越大或越来越多,文档也会增长,这会导致文档检索时间变慢 .

    请参阅此页面有关构建数据的不同策略的优缺点的更多信息:https://firebase.google.com/docs/firestore/manage-data/structure-data

  • 0

    我不相信目前存在你正在寻找的开关,所以我认为留下以下内容,

    • 全局禁用内置索引并显式创建所有索引 . 痛苦,他们也有限制 .

    • 一种解决方法,您可以像对待BLOB一样对待Cloud Firestore不友好的内容,如下所示:

    储藏,

    const objIn = {text: 'my object with a zillion fields' };
    const jsonString  = JSON.stringify(this.objIn);
    const container = { content: this.jsonString };
    

    要检索,

    const objOut = JSON.parse(container.content);
    

相关问题