为何CosmosDB默认不索引数组?默认索引路径/*为何不包含数组?
/*不包含数组? 这其实是Cosmos DB索引策略里一个容易被误解的点,我来给你拆解清楚:
核心原因:/*的实际覆盖范围不包含数组内部元素
Cosmos DB默认的索引路径"path": "/*"看起来是“索引所有内容”,但它的实际逻辑是只索引文档中的顶级属性、嵌套对象的属性,不会自动深入数组内部索引单个元素。
举个例子,假设你的文档是这样的:
{ "id": "1", "name": "test", "tags": ["a", "b", "c"] }
默认索引会索引/id、/name,也会把整个/tags数组作为一个整体索引,但不会单独索引tags里的"a"、"b"、"c"这些元素。这就导致当你用Array_Contains(c.tags, "a")查询时,数据库没办法通过索引快速定位到包含该元素的文档,只能做全表扫描,所以速度极慢。
数组索引的特殊语法
当你添加"path": "/tags/[]/?"这个索引时,你其实是告诉Cosmos DB:深入tags数组,为数组里的每个元素建立单独索引。这里的[]表示匹配数组的任意元素,?表示匹配元素的任意属性(如果是对象数组的话,比如tags是[{"name":"a"},...],这个语法也能覆盖;如果是简单值数组,"/tags/[]"就足够了)。
有了这个索引后,Cosmos DB会把数组里的每个值都单独存入索引,Array_Contains查询就能直接命中索引,快速筛选出符合条件的文档,速度自然就上去了。
为什么默认不这么做?
这是Cosmos DB在性能和灵活性之间做的权衡:如果自动为所有数组元素建立索引,对于包含大量数组或大数组的文档,会大幅增加索引的存储体积,同时也会提升写入文档时的索引更新成本。默认策略把这个选择权交给开发者,让你根据自己的查询需求来决定是否为特定数组字段开启内部索引,避免不必要的性能损耗。
内容的提问来源于stack exchange,提问作者BowserKingKoopa

