Cosmos DB,如果我在使用 SkipToken 查询时更新某些项目会发生啥?

Posted

技术标签:

【中文标题】Cosmos DB,如果我在使用 SkipToken 查询时更新某些项目会发生啥?【英文标题】:Cosmos DB, What will happen If I update some item when query with SkipToken?Cosmos DB,如果我在使用 SkipToken 查询时更新某些项目会发生什么? 【发布时间】:2021-07-13 11:19:20 【问题描述】:

如果我使用 SkipToken 从 CosmosDB 查询项目,

喜欢伪代码:

do
   var page = Query();
   foreach(var item in page)
   
      Update(item);
   
while(HasNextPage());

我得到的page可能不完整,这意味着我会错过一些项目。

但如果我在Update 之后稍等片刻 喜欢:

do
   var page = Query();
   foreach(var item in page)
   
      Update(item);
   

   // difference here:
   WaitAMoment();
while(HasNextPage());

,错误不会发生,我会得到我需要的完整页面。

那么这个过程发生了什么?

【问题讨论】:

您能添加Query() 的详细信息吗?使用sql,我可能会尝试在我身边重现问题。 【参考方案1】:

您不必在代码中等待,此功能由 CosmosDB 内部处理。查看Pagination in SDKs of Cosmos DB,例如,我在下面的 C# 中添加处理服务器端分页的代码(了解它的工作原理):

private static async Task QueryPartitionedContainerInParallelAsync(Container container)
        
            List<Family> familiesSerial = new List<Family>();
            string queryText = "SELECT * FROM Families";

            // 0 maximum parallel tasks, effectively serial execution
            QueryRequestOptions options = new QueryRequestOptions()  MaxBufferedItemCount = 100 ;
            options.MaxConcurrency = 0;
            using (FeedIterator<Family> query = container.GetItemQueryIterator<Family>(
                queryText,
                requestOptions: options))
            
                while (query.HasMoreResults)
                
                    foreach (Family family in await query.ReadNextAsync())
                    
                        familiesSerial.Add(family);
                    
                
            

            Assert("Parallel Query expected two families", familiesSerial.ToList().Count == 2);

            // 1 maximum parallel tasks, 1 dedicated asynchronous task to continuously make REST calls
            List<Family> familiesParallel1 = new List<Family>();

            options.MaxConcurrency = 1;
            using (FeedIterator<Family> query = container.GetItemQueryIterator<Family>(
                queryText,
                requestOptions: options))
            
                while (query.HasMoreResults)
                
                    foreach (Family family in await query.ReadNextAsync())
                    
                        familiesParallel1.Add(family);
                    
                
            

            Assert("Parallel Query expected two families", familiesParallel1.ToList().Count == 2);
            AssertSequenceEqual("Parallel query returns result out of order compared to serial execution", familiesSerial, familiesParallel1);


            // 10 maximum parallel tasks, a maximum of 10 dedicated asynchronous tasks to continuously make REST calls
            List<Family> familiesParallel10 = new List<Family>();

            options.MaxConcurrency = 10;
            using (FeedIterator<Family> query = container.GetItemQueryIterator<Family>(
                queryText,
                requestOptions: options))
            
                while (query.HasMoreResults)
                
                    foreach (Family family in await query.ReadNextAsync())
                    
                        familiesParallel10.Add(family);
                    
                
            

            Assert("Parallel Query expected two families", familiesParallel10.ToList().Count == 2);
            AssertSequenceEqual("Parallel query returns result out of order compared to serial execution", familiesSerial, familiesParallel10);
        

【讨论】:

以上是关于Cosmos DB,如果我在使用 SkipToken 查询时更新某些项目会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

Azure Cosmos DB:使用 UpsertDocumentAsync 违反唯一索引约束

Cosmos DB - ExecuteNextAsync 返回空对象

azure cosmos db 在 mongodb.com 中创建了集合

azure cosmos db 在 mongodb.com 中创建了集合

Cosmos DB 补丁子对象

如何确保我的 get 查询不会受到 COSMOS db 中长时间运行的更新的影响?