如何允许将 Odata 选项应用于 cosmos db 集合并返回过滤后的记录

Posted

技术标签:

【中文标题】如何允许将 Odata 选项应用于 cosmos db 集合并返回过滤后的记录【英文标题】:How to allow Odata options to be applied to cosmos db collection and return filtered records 【发布时间】:2020-11-30 05:10:15 【问题描述】:

我需要在 api 上实现分页。我正在执行以下操作以在 api 上启用 OData 查询,但它在从 cosmos db 获取所有记录后进行过滤,但我想从 cosmos db 中获取过滤后的记录。如何将 Odata 查询选项转换为 cosmos db 查询选项?

 controller.cs

            [Route("apps")]
            [HttpGet]
            [EnableQuery]
            public async Task<IActionResult> GetAllApps(CancellationToken cancellationToken)
            
                var user = this.GetUser();
                var results = await this.appRepository.GetAppsForUserAsync(user, cancellationToken).ConfigureAwait(false);
                return this.Ok(this.mapper.Map<AppHeader[]>(results));
            
AppRepository.cs
 public async Task<IEnumerable<App>> GetAppsForUserAsync(User user, CancellationToken cancellationToken)
                    
            try
            
                FeedOptions queryOptions = new FeedOptions
                
                    MaxItemCount = -1,
                    PartitionKey = new PartitionKey(user)
                ;

                var query = this.factory.GetClient()
                    .CreateDocumentQuery<App>(
                        UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName),
                        queryOptions)
                    .Where(resource => resource.UserList.Any(u => u.userId == user.Id))
                    .AsDocumentQuery();

                List<App> results = new List<App>();
                while (query.HasMoreResults)
                
                    cancellationToken.ThrowIfCancellationRequested();

                    var response = await query.ExecuteNextAsync<App>(cancellationToken).ConfigureAwait(false);

                    var app = this.mapper.Map<App[]>(response);
                    results.AddRange(app);
                

                return results;
            
            catch (DocumentClientException ex)
            
                this.logger.LogError(ex, ex.Message);
                throw;
            
        
Client.js

http://localhost:8303/api/appdefinitions/my?$skip=6&$top=4`

【问题讨论】:

【参考方案1】:

在存储库中,尝试使用GetItemLinqQueryable 并对其进行查询。请注意,我在这里使用的是较新的 V3 SDK Microsoft.Azure.Cosmos,但旧版 SDK 中也应该存在等效项。

// Take `skip` and `top` params as input to the repository method.

List<App> results = new List<App>();
using (CosmosClient client = new CosmosClient(endpoint, authKey))

  Database cosmosDatabase = await client.CreateDatabaseIfNotExistsAsync(DatabaseName);
  Container container = await Program.GetOrCreateContainerAsync(cosmosDatabase, CollectionName);
  // LINQ query generation
  using (FeedIterator setIterator = container.GetItemLinqQueryable<App>()
                     .Where(a => a.userId == user.Id)
                     .Skip(skip)
                     .Take(top)
                     .ToFeedIterator())
                     
      //Asynchronous query execution
      while (setIterator.HasMoreResults)
      
          var items = await feedIterator.ReadNextAsync().ConfigureAwait(false);
          results.AddRange(items);
      
  

注意:理想情况下,在实际应用程序中,您应该重用 CosmosClient 实例,而不是每次都为 performance improvement 创建。

【讨论】:

感谢您的回答!。我会考虑这一点,但是如何将 skip 和 top 参数作为输入传递给存储库方法?如何建模从客户端到控制器的绑定跳过和顶部? 您可以通过控制器操作绑定到ODataQueryOptions 模型。 我同意您的选择,但就我而言,我想在不使用更新的 V3 SDK Microsoft.Azure.Cosmos 的情况下实现该功能

以上是关于如何允许将 Odata 选项应用于 cosmos db 集合并返回过滤后的记录的主要内容,如果未能解决你的问题,请参考以下文章

Sitefinity权限如何应用于oData Web服务?

WebAPI Odata 在无类型实体上应用查询选项

如何通过 Azure 虚拟网络从 power bi 桌面应用程序连接到 cosmos db

WebAPI OData v4 查询不是异步的?

如何使用 Cassandra API 将 Python 的 cosmos_client 连接到 Cosmos DB 实例?

将 ODATA $expand 查询选项与 WebAPI 和 ViewModel 一起使用