2016-01-31 4 views
6

C#でLinqプロバイダの有無にかかわらずDocumentDBに対してページ作成を実装する方法があるのだろうか?C#でスキップせずにDocumentDBに対して

シナリオ:

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

私は、ページ付けし、それらのパラメータを使用します。私は、ページネーションをサポートAPIを持って、ユーザーは、彼らのような、pageSizeを一緒に見たいページに送信します次のコードでデータアクセス層のデータ:

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

は「その問題は何ですか?」、あなたは尋ねるかもしれません。 EFとSQLを使用している間、この手法とコードは完全に機能します。問題は、DocumentDBの使用を開始したいが、Linq実装ではSkipをサポートしていないことです。私が見た唯一の例は、TOPキーワード、またはを使用して、ではなく、が私によく合い、pageNumberとpageSizeで送信できるようにしています。

要求にpageNumberpageSizeを提供できる実装はありますか?

答えて

11

SKIPはSQLのパフォーマンス上の問題であり、スケールアウト設計のためNoSQLにとってさらに悪化します。 MongoDBのSKIP機能を使用して、スキップされた行をすべて破棄してクエリを本質的に元に戻すことがわかった。私たちがスキップしていたリストの後半では、クエリにかかる時間が長くなりました。したがって、SKIP機能を備えていても、よりパフォーマンスの高いソリューションを実装する必要がありました。

DocumentDBのプロダクトマネージャーはこれを理解しており、SKIPを追加することはできません。もし彼らがそれをやろうとすれば、彼らはTOPを追加したときにそれをやったと思います。

DocumentDBの場合、最も効率的なアプローチは、継続トークンを使用して、すべての結果をユーザーが望むところまで(予想通りに)までキャッシュすることです。継続トークンは長い間生き残り​​ます。そのため、すぐにすべてのページを取得する必要はありません。

+1

こんにちはラリー、 は、あなたの答えをありがとう、合理的な引数を作ることのように聞こえる:ここに私のソリューションです。私はどのように継続トークンを使用してキャッシングを見ることができませんが、私のユーザが 'page'と' pageSize'の組み合わせを送ることができれば、結果は実現可能です。 はい、ページの最高値はコレクション内のアイテムの数と等しくなりますが、 'page'と' pageSize'コンボによって得られたすべての異なる組み合わせと一緒にこれをキャッシュするのは「不可能」ではないでしょうか? 'pageSize'は1から約50までの全てであることに注意してください。 –

+2

ユーザがページサイズを10に設定し、キャッシュ内に27行を持っているとしましょう。したがって、キャッシュには、ユーザーがページ7を要求したときに、ページ1、ページ2、およびページ3の一部だけがメモリに格納されます。コードでは、ページ7を表示するためにキャッシュに少なくとも80行が必要であると計算されます。最後のリクエストからの継続トークンを使用してその行を多数取得します。その後、ユーザーが5ページ目に戻ってきたら、すでにキャッシュに保存されているので、DocumentDBを押す必要はありません。実際には、2桁のミリ秒単位で100または1000の行を取得することができます。 –

+0

ありがとうございます。これは良い戦略のように思えます。特に、ユーザーがさまざまなリクエスト間で 'pageSize 'を変更できるように十分に動的であるためです。私はあなたが単一のリソースの要求で構築されたキャッシュを使用することもできたと思います。これは素晴らしいことです。 –

5

これはあなたの質問に具体的には答えませんが、将来のGoogle社員にとってDocument DBは継続トークンによるページングをサポートしています。私はそれを詳細に書いたhere。あなたはそれを、この必要なコード:

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 
} 
4

を私は質問がすでに受け入れ(よく言った)答えを持っていますが、私は、私は共有するだろうと思った「DocumentDBはスキップ」のために、この特定のSOページがGoogleで上位の結果であることから実現私の解決策はここにあります。これは実際にはラリーがすでに提案しているものの実装です。私は、継続トークンを使用し、Angularでキャッシュすることで、DocumentDBクエリの適切なページングメカニズムが実現しました。重要なのは、並べ替えやフィルタリングを許可することで、ユーザーがランダムなページにジャンプしたり、結果の最後のページにジャンプしたりする必要がなくなることです。

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

+0

偉大な解決策。私は本当に次のページの代わりにナビゲーション内のすべてのページ(ランダムジャンプ)を表示することをサポートするように更新されたのを見たいと思っています。 – defines