Azure Cosmos DB中的奇怪查询结果

时间:2018-11-07 11:09:00

标签: azure azure-cosmosdb

我的Azure Cosmos数据库中有以下文档:

{
    "id": "token",
    "User": {
        "UserToken": "token",
        "Email": "test@email.com"
    },
    "_ts": 1541493290
}

当我运行以下查询时:

SELECT * FROM root  
WHERE ((root["User"]["UserToken"] = "token")  
OR CONTAINS(root["User"]["Email"], "token"))  
ORDER BY root["_ts"] DESC 

什么都不返回。但是当我改变它的时候。例如,将Email转换为email

SELECT * FROM root  
WHERE ((root["User"]["UserToken"] = "token")  
OR CONTAINS(root["User"]["email"], "token"))  
ORDER BY root["_ts"] DESC 

找到结果。此外,当我删除ORDER BY子句时,查询也会返回一个结果。所以查询就像下面的

SELECT * FROM root  
WHERE ((root["User"]["UserToken"] = "token")  
OR CONTAINS(root["User"]["Email"], "token"))  

此外,当我编辑文档时(如打开文档,添加空行并保存),背景中发生了一些魔术,并找到了文档。对于相当“新”的文档(少于1-3个月),我无需使用“魔术”技巧就可以进行搜索。

索引的定义是:

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*",
            "indexes": [
                {
                    "kind": "Range",
                    "dataType": "Number",
                    "precision": -1
                },
                {
                    "kind": "Hash",
                    "dataType": "String",
                    "precision": 3
                }
            ]
        }
    ],
    "excludedPaths": []
}

我做错了什么?

更新答案不是一个完整的解释,但很有帮助。完整的解释在我的博客(https://stapp.space/ridiculous-bug-in-azure-cosmos-db/

1 个答案:

答案 0 :(得分:1)

如果您将字符串索引为CONTAINS(root["User"]["Email"], "token"),则

Hash将不起作用。它们必须是Range,精度为-1。哈希仅适用于相等性检查。

这就是小写字母起作用的原因。因为它找不到属性,而只是忽略它,所以退回到相等检查。第一个找到它,发现它没有索引为Range,只是返回失败。

更改对此的索引将起作用:

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*",
            "indexes": [
                {
                    "kind": "Range",
                    "dataType": "Number",
                    "precision": -1
                },
                {
                    "kind": "Range",
                    "dataType": "String",
                    "precision": -1
                }
            ]
        }
    ],
    "excludedPaths": []
}

另一方面,_ts字段不是基于创建进行排序的最佳方法。这是一个以秒为单位的unix时间戳,因此在同一秒内创建的任何文档都将无法正确排序。