【问题标题】:Strange query results in Azure Cosmos DBAzure Cosmos DB 中的奇怪查询结果
【发布时间】:2018-11-07 11:08:59
【问题描述】:

我的 Azure Cosmos DB 中有以下文档:

{
    "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": []
}

我做错了什么?

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

【问题讨论】:

    标签: azure azure-cosmosdb


    【解决方案1】:

    如果您有索引为Hash 的字符串,CONTAINS(root["User"]["Email"], "token") 将不起作用。它们必须是 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 时间戳,因此在同一秒内创建的任何文档都不会正确排序。

    【讨论】:

    • 如何强制“重新索引”?我做了上面的改变,什么也没发生。
    • 还有一件事。第二个原因是 100% 不稳定。但是我还是不知道1st和3rd有什么区别?
    • 重新索引将在保存更改后自动启动。您可以通过代码跟踪进度。但是,使用 _ts 字段排序可能不起作用,因为它有自己的索引策略,因为它是系统定义的元属性。我自己遇到了很多问题,最终我创建了自己的属性,以毫秒精度进行创建时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 2020-05-11
    • 2017-02-26
    相关资源
    最近更新 更多