没有Skip的C#对DocumentDB的分页

Joa*_*oog 7 c# linq pagination azure-cosmosdb

我想知道是否有任何方法可以使用或不使用他们的Linq提供程序在C#中对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在请求中?

Lar*_*one 11

SKIP是SQL的一个性能问题,由于它们的横向扩展设计,它对NoSQL来说更糟糕.我们使用了MongoDB的SKIP功能,发现它实际上从头开始重新删除所有跳过的行.我们跳过的列表中的后面,查询所用的时间越长.因此,即使它具有SKIP功能,我们也被迫实施更高性能的解决方案.

DocumentDB的产品经理了解这一点并且无法添加SKIP.如果他们打算这样做,我相信他们会在添加TOP时做到这一点.

对于DocumentDB,最有效的方法是使用延续令牌并将所有结果缓存到用户想要的位置(甚至超出预期).持续令牌可以存活很长时间,因此您无需立即获取所有页面.

  • 假设用户已将页面大小设置为10,并且缓存中有27行.因此,当用户请求第7页时,缓存只有足够的行用于第1页,第2页和内存中第3页的一部分.您的代码会计算出它需要在缓存中至少有80行才能显示第7​​页和它将使用上一个请求中的延续令牌来获取那么多行.如果用户然后跳回到第5页,那么你已经在缓存中拥有它,并且不需要访问DocumentDB.在实践中,您可以以两位数毫秒的速度获得100行甚至1000行. (2认同)
  • 请注意,延续令牌永不过期/sf/ask/2958512511/ (2认同)

Kev*_*zyk 6

虽然这没有具体回答您的问题,但对于未来的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
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*Dan 5

我意识到这个问题已经有了一个被接受的(而且说得很好的)答案,但由于这个特定的SO页面是Google上“DocumentDB跳过”的最佳结果,我想我会在这里分享我的解决方案,这实际上只是Larry所拥有的解决方案的实现已经建议了。我在 Angular 中使用了延续令牌和缓存,为 DocumentDB 查询提供了一个不错的分页机制。关键是我还允许排序和过滤,这减少了用户跳转到随机页面甚至结果最后一页的需要。这是我的解决方案:

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