これは「フォワードページング」と呼ばれ、「ソートされた」結果を使用するときに、結果を「フォワード」方向に「効率的にページング」するために使用できる概念です。
JavaScriptロジックが含まれていますが(シェルで機能するため)、変換するのは難しくありません。
一般的な概念:
{ "_id": 1, "a": 3 },
{ "_id": 2, "a": 3 },
{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },
{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }
1ページに「2」個のアイテムで「ページ」したい結果の例として、これらの「すでにソートされた」ドキュメント(便宜上)を考えてみてください。
最初に、次のようなことを行います:
var lastVal = null,
lastSeen = [];
db.collection.find().sort({ "a": -1 }).limit(2).forEach(function(doc) {
if ( lastVal != doc.a ) {
lastSeen = [];
}
lastVal = doc.a;
lastSeen.push( doc._id );
// do something useful with each document matched
});
今、それらのlastVal
およびlastSeen
「セッション変数」のようなものに保存するものであり、Webアプリケーションに関して次のリクエストでアクセスできるもの、またはそうでない場合は同様のものです。
ただし、それらに含まれるべきものは、ソートした最後の値と「一意の」_id
のリストです。 その値以降に見られた値は変化しませんでした。したがって:
lastVal = 3,
lastSeen = [1,2];
重要なのは、「次のページ」のリクエストが来たら、これらの変数を次のようなものに使用したいということです。
var lastVal = 3,
lastSeen = [1,2];
db.collection.find({
"_id": { "$nin": lastSeen },
"a": { "$lte": lastVal }
}).sort({ "a": -1 }).limit(2).forEach(function(doc) {
if ( lastVal != doc.a ) {
lastSeen = [];
}
lastVal = doc.a;
lastSeen.push( doc._id );
// do something useful with each document matched
});
これは、_id
のすべての値を「除外」することです。 lastSeen
に記録されている 結果のリストから、すべての結果がlastVal
の「以下」(降順)である必要があることを確認します。 ソートフィールド「a」に記録されます。
これにより、コレクションに次の2つの結果が生成されます。
{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },
しかし、処理後の値は次のようになります:
lastVal = 2,
lastSeen = [4];
したがって、他の_id
を除外する必要がないというロジックが続きます。 lastVal
よりも「以下」の「a」の値のみを実際に探しているために以前に表示された値 _id
は「1つ」しかなかったので その値で見られる値は、その値のみを除外します。
もちろん、これにより、上記と同じコードの使用に関する次のページが表示されます。
{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }
これは、一般的に結果を「ページを転送」するための最も効率的な方法であり、「ソートされた」結果の効率的なページングに特に役立ちます。
ただし、20
ページに「ジャンプ」したい場合 または任意の段階で同様のアクションを実行すると、これはあなたのためではありません。従来の.skip()
に固執しています および.limit()
これを「計算」する他の合理的な方法がないため、「ページ番号」でこれを実行できるようにするアプローチ。
したがって、それはすべて、アプリケーションが「ページング」をどのように実装しているか、および何を使用できるかに依存します。 .skip()
および.limit()
このアプローチは「スキップ」のパフォーマンスを低下させるため、ここでのアプローチを使用することで回避できます。
一方、「ページにジャンプ」したい場合は、結果の「キャッシュ」を作成したい場合を除いて、「スキップ」が唯一の現実的なオプションです。しかし、それはまったく別の問題です。