在 CosmosDB 中使用 CosmosClient 进行分页

Fra*_*rme 3 c# azure-cosmosdb asp.net-core-3.0

我正在尝试使用 SDK v3CosmosClient而不是旧的DocumentClient.

这样做的原因是它似乎DocumentClient不能很好地转换包含空间函数的 LINQ 查询(即:使用时,Within()我会从 DocumentClient 收到一个错误,说明未实现这些方法)。

分页适用DocumentClient.CreateDocumentQuery<T>于以下情况:

var query = DocumentClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri("master", "features"), feedOptions)
                .Where(t => t.Type == typeof(T).Name)
                .Where(pred)
                .AsDocumentQuery();

string queryContinuationToken = null;
var page = await query.ExecuteNextAsync<T>();
if (query.HasMoreResults)
    queryContinuationToken = page.ResponseContinuation;
Run Code Online (Sandbox Code Playgroud)

我不知道在哪里收集使用CosmosClient及其Container类的延续令牌:

QueryRequestOptions options = new QueryRequestOptions();
options.MaxItemCount = maxRecords;

FeedIterator<T> feed;

if (continuationToken == "")
    feed = Container.GetItemLinqQueryable<T>(true, null, options).Where(x => x.Type == typeof(T).Name).Where(pred).ToFeedIterator();
else
    feed = Container.GetItemLinqQueryable<T>(true, continuationToken, options).Where(x => x.Type == typeof(T).Name).Where(pred).ToFeedIterator();
Run Code Online (Sandbox Code Playgroud)

FeedIterator似乎有一些成员IDocumentQuery拥有(如HasMoreResults),但我在任何地方都找不到延续令牌。

我错过了什么?

Fra*_*rme 8

好的,这是Where我实现的方法。乍一看似乎有效。

如果这样做,var f = feed.ReadNextAsync()您将不会获得类型为 的对象FeedResponse,从而阻止您访问令牌。您需要f明确声明类型FeedResponse<T>

public async Task<(IEnumerable<T> Results, string ContinuationToken)> Where<T>(Expression<Func<T, bool>> pred, int maxRecords = 0, string partitionKey = "", string continuationToken = "") where T : IDocumentModel
{

    QueryRequestOptions options = new QueryRequestOptions();

    if (partitionKey != "")
        options.PartitionKey = new PartitionKey(partitionKey);


    if (maxRecords == 0)
    {
        return (Container.GetItemLinqQueryable<T>(true, null, options).Where(x => x.Type == typeof(T).Name).Where(pred), "");
    }
    else
    {
        options.MaxItemCount = maxRecords;
        string token = "";
        FeedIterator<T> feed;
        List<T> res = new List<T>();

        if (continuationToken == "")
            feed = Container.GetItemLinqQueryable<T>(true, null, options).Where(x => x.Type == typeof(T).Name).Where(pred).ToFeedIterator();
        else
            feed = Container.GetItemLinqQueryable<T>(true, continuationToken, options).Where(x => x.Type == typeof(T).Name).Where(pred).ToFeedIterator();

        Microsoft.Azure.Cosmos.FeedResponse<T> f = await feed.ReadNextAsync();
        token = f.ContinuationToken;

        foreach (var item in f)
        {
            res.Add(item);
        }

        return (res, token);
    }

}
Run Code Online (Sandbox Code Playgroud)