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

问题描述 投票:0回答:2

我有一个在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`
.net-core odata azure-cosmosdb paging webapi
2个回答
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
实例,而不是每次都创建 性能改进


0
投票

使用 CosmosLINQ Query 直接应用所有 ODataQuery 选项。

使用 Microsoft.Azure.Cosmos.Client 版本 3.32.1.0 进行测试

var odataQuery = odataQueryOptions.ApplyTo(
                container.GetItemLinqQueryable<TargetODataModel>(allowSynchronousQueryExecution: false),
                _odataQuerySettings) as IQueryable<TargetODataModel>;
            return await odataQuery.ToFeedIterator().ReadNextAsync(cancellationToken);
© www.soinside.com 2019 - 2024. All rights reserved.