Azure Cosmosdb(Documentdb)默认索引策略不适用于StartsWith()函数

Azure Cosmosdb(Documentdb)默认索引策略不适用于StartsWith()函数,azure,indexing,azure-cosmosdb,Azure,Indexing,Azure Cosmosdb,我在运行查询时遇到以下异常 SELECT TOP 10 c.name FROM Customer c WHERE STARTSWITH(c.name, 'Bob') 例外情况: An invalid query has been specified with filters against path(s) that are not range-indexed. Consider adding allow scan header in the request. 我通过将索引更改为 {

我在运行查询时遇到以下异常

SELECT TOP 10 c.name
FROM Customer c
WHERE STARTSWITH(c.name, 'Bob')
例外情况:

An invalid query has been specified with filters against path(s) that are not range-indexed. Consider adding allow scan header in the request.
我通过将索引更改为

{
    "path": "/",
    "indexes": [
        {
            "kind": "Range",
            "dataType": "Number",
            "precision": -1
        },
        {
            "kind": "Hash",
            "dataType": "String",
            "precision": 3
        }
    ]
},
{
    "path": "/name/?",
    "indexes": [
        {
            "kind": "Range",
            "dataType": "String",
            "precision": -1
        }
    ]
}
但我有两个问题:

为什么默认索引不起作用?路径:/*不应该索引所有内容吗? 为什么必须添加路径:/?你为什么需要它?
顺便说一句,我已经阅读了关于索引策略的部分,但仍然不理解它。感谢您的帮助

我想我可能已经找到了问题的答案

默认路径:/*不起作用的原因是,范围索引的数据类型设置为Number,而name的值显然是string。这就是为什么我需要为name添加一个额外的范围索引

我还注意到path:/*和path:/产生相同的结果。我想它们是可以互换的。

为什么默认索引不起作用?路径:/*不应该索引所有内容吗? 是的,但重要的是如何

默认索引不起作用,因为对于数据类型字符串,它是作为哈希索引创建的。散列意味着索引不存储实际值,而是存储由某些索引生成的较小的加扰散列值。要获得匹配,需要与生成相同哈希的值进行比较。假设具有合理长度的高质量散列函数,它将需要相同的原始值。因此,c.name=Bob将被该索引覆盖

还通过以下方式确认:

索引类 哈希支持高效的相等和联接查询

您的查询谓词STARTSWITHc.name,'Bob'正在对c.name属性执行函数检查。StartWith无法在不扫描所有文档的情况下生成所有可能的匹配哈希值进行比较。 因此,正如错误所述:给定属性上的索引无法服务于此查询

为什么必须添加路径:/?你为什么需要它?

我不确定是否与应用隐式默认值相比,它在技术上是强制性的,但我认为这是一个合理的要求,让用户明确地盯着默认值并批准或修改它们。 按比例设计-从不进行全扫描。 另一方面,DocumentDB是为处理集合而设计的关系SQL数据库,它是为无模式的非结构化数据而设计的,为处理单个文档而优化,并为扩展而设计。您不应该进行完全扫描并读取所有文档,因为它不会缩放。因此,您应该设计和计划如何查询数据

违约几乎从来都不是最优的。 正如您所经历的,每个索引都有不同的目标-范围索引支持排序,但哈希索引更紧凑,使用更快。此外,合适的索引精度取决于您的数据、值分布和应用需要

成本影响。 此外,每个索引都有存储成本,并且在每次插入/更新/删除时都需要额外的努力来保持同步。因此,索引选择会影响性能和账单。你可能两者都关心