我有一个在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`
在存储库中,尝试使用 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
实例,而不是每次都创建 性能改进。
使用 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);