在 C# 中针对 DocumentDB 进行分页,无需跳过

本文关键字:分页 DocumentDB | 更新日期: 2023-09-27 18:32:43

我想知道是否有任何方法可以在 C# 中使用或不使用其 Linq 提供程序对 DocumentDB 实现分页?

场景:我有一个支持分页的 API,用户发送他们想要查看的页面以及 pageSize,例如:

public virtual async Task<HttpResponseMessage> Get(int? page = DefaultPage, int? pageSize = DefaultPageSize)

然后,我使用这些参数使用以下代码对数据访问层中的数据进行分页:

return query.Skip((pageNumber - 1) * pageSize).Take(pageSize);

"那有什么问题?",你可能会问。嗯,这种方法和代码在使用 EF 和 SQL 时完美运行。问题是我想开始使用 DocumentDB,但他们的 Linq 实现不支持 Skip。我看到的唯一示例包括使用 TOP 关键字或延续标记,这与我不太适合允许用户发送 pageNumber 和 pageSize 的情况。

是否有任何实现仍允许我的用户在请求中提供pageNumberpageSize

在 C# 中针对 DocumentDB 进行分页,无需跳过

SKIP 是 SQL 的性能问题,由于其横向扩展设计,对于 NoSQL 来说甚至更糟。我们使用了MongoDB的SKIP功能,发现它基本上从头开始重新运行查询,丢弃了所有跳过的行。我们跳到列表的后面,查询花费的时间就越长。因此,即使它具有 SKIP 功能,我们也被迫实现性能更高的解决方案。

DocumentDB的产品经理理解这一点,并且拒绝添加SKIP。如果他们要这样做,我相信他们在添加 TOP 时会这样做。

对于 DocumentDB,最有效的方法是使用继续标记并按顺序缓存所有结果,直到(甚至可以预见地超出)用户所需的位置。延续令牌可以存活很长时间,因此无需立即提取所有页面。

虽然这并不能具体回答您的问题,但对于未来的 Google 员工,Document DB 支持通过延续令牌进行分页。 我在这里详细写了。 你需要的代码是这样的:

var endpoint = "document db url";  
var primaryKey = "document db key";  
var client = new DocumentClient(new Uri(endpoint), primaryKey);  
var collection = UriFactory.CreateDocumentCollectionUri("database id", "collection id");
var options = new FeedOptions  
{ 
    MaxItemCount = 100 // <- Page size
};
var query = client.CreateDocumentQuery<Document>(collection, options).AsDocumentQuery();
while (query.HasMoreResults)  
{
    var result = await query.ExecuteNextAsync<Document>();
    // Process paged results
}
<</div> div class="answers">

我意识到这个问题已经有一个公认的(并且说得很好)的答案,但由于这个特定的 SO 页面是谷歌上"DocumentDB skip"的最佳结果,我想我会在这里分享我的解决方案,这实际上只是拉里已经建议的实现。 我在 Angular 中使用了继续标记和缓存来为 DocumentDB 查询提供一种不错的分页机制。 关键是我还允许排序和过滤,这减少了用户跳转到随机页面甚至结果最后一页的需要。 这是我的解决方案:

http://www.zoeller.us/blog/2017/7/27/paging-results-with-documentdb