对分区CosmosDB集合的查询不一致

时间:2018-12-10 04:11:40

标签: c# .net-core azure-cosmosdb database-partitioning

我有一个分区的cosmos DB集合,该集合定义为无限制,吞吐量为1000。它具有以下文档结构:

"Id": "b42129d2-5467-450c-9f7e-744f78dfe1e7", // Primary key
"ArrayOfObjects": [
 {
     // other properties omitted for brevity
     "SubId": "ed2a49fb-51d4-45b4-9690-df0721d6a32f"
 },
 {
     "SubId": "35c87833-9bea-4151-86da-4d9c482ae1fe"
 },
 "ParitionKey": "b42"

分区键是主键(即GUID)的前3个字母。这为我提供了32768个具有良好基数的可能分区。我正在使用CosmosDB .NetCore SDK。目前,在约6000个分区中有约17万个文档。

我具有一些功能,需要通过“ SubId”从集合中检索文档,而我不知道主键,这意味着我不知道分区键。不幸的是,我不能更改此功能以使其与主键一起使用,因为它的依赖项是无法修改的旧系统。

发生的事情是,我成功创建了一个新文档,然后在某个时候我需要使用“ SubId”查询该文档。这是在C#中完成的,如下所示:

public async Task<DocumentModel> GetBySubId(string subId)
{
    var collectionId = _cosmosClient.CollectionId;
    var query = $@"SELECT * FROM {collectionId} c
                   WHERE ARRAY_CONTAINS(c.ArrayOfObjects, {{'SubId': '{subId}'}}, true)";

    var feedOptions = new FeedOptions { EnableCrossPartitionQuery = true };

    var docQuery = _cosmosClient.Client.CreateDocumentQuery(
            _collectionUri,
            query,
            feedOptions)
            .AsDocumentQuery();

    var executedQuery = await docQuery.ExecuteNextAsync<DocumentModel>();

     if (executedQuery.Count == 0)
     {
           return null;
     }

     return executedQuery.FirstOrDefault();
}

有时它成功查询有时不成功,并且我返回null,然后从我的控制器中返回404。

之所以如此奇怪是因为,如果我检查数据库并直接运行该查询,则文档在那里并且实际上并没有丢失,但是由于某些原因,当我使用SDK从C#查询时,找不到该文档。我还有其他功能可以使用主键(现在意味着我拥有分区键)和SubId进行查询,并且可以正常工作。只有当我自己(不使用分区键)使用SubId进行查询时,找不到文档。

鉴于上述情况,我认为这与没有分区键的查询有关。在没有分区键的情况下查询时我缺少什么?

此刻我尝试将database consistency从“最终”设置为“强”。这似乎没有什么区别。

2 个答案:

答案 0 :(得分:2)

我来自CosmosDB工程团队。

您提到的行为可能是因为,偶尔,该查询无法在一个延续上完成执行。请确保通过耗尽连续性来完成查询的执行。您可以在这里找到示例:https://docs.microsoft.com/en-us/azure/cosmos-db/performance-tips#throughput。在IDocumentQuery.HasMoreResults设置为false之前,查询执行才被视为完成。

答案 1 :(得分:1)

  

我目前尝试的是从   最终变强。这似乎没有什么区别。

Strong级别开始,EnableCrossPartitionQuery = true级别的一致性保证返回项目的最新提交版本。根据您的描述,您正在测试的环境不是高并发读取操作。因此,我认为这与一致性级别无关。

  

有时它查询成功有时不成功,我返回   null,然后从我的控制器返回404。

根据我的经验,由于吞吐量瓶颈,此问题反复出现。查询分区集合时,需要提供分区键。但是,您不知道分区键,只有在设置示例代码中已经存在的array_contains后才能完成。然后,您的查询将跨整个分区,直到找到特定的文档。另外,var cognitoUser = result.user;运算符增加了查询负担。

Cosmos DB查询受到吞吐量设置的限制,不会无限覆盖整个数据库。请参阅此document

由于您现在无法调整分区策略,因此建议您增加吞吐量设置以检查问题。