web-dev-qa-db-ja.com

MongoDBページネーションの範囲クエリ

MongoDBの上にページネーションを実装したい。私の範囲クエリでは、ObjectIDの使用を検討しました。

db.tweets.find({ _id: { $lt: maxID } }, { limit: 50 })

ただし、 ドキュメントによれば 、ObjectIDの構造は、「ObjectId値は厳密な挿入順序を表していない」ことを意味します。

ObjectId値の順序と生成時間の関係は、1秒以内に厳密ではありません。 複数のシステム、または単一のシステム上の複数のプロセスまたはスレッドが1秒以内に値を生成する場合。 ObjectId値は厳密な挿入順序を表しません。クライアントドライバーはmongodプロセスではなくObjectId値を生成するため、クライアント間のクロックスキューは値に対しても厳密でない順序になる可能性があります。

次に、タイムスタンプを使用したクエリについて考えました。

db.tweets.find({ created: { $lt: maxDate } }, { limit: 50 })

ただし、日付が一意であるという保証はありません。同じ秒内に2つのドキュメントが作成される可能性が高いです。これは、ページング時にドキュメントを見逃す可能性があることを意味します。

安定性を高める範囲クエリはありますか?

35
user1082754

ページネーションの構文は間違っていますが、ObjectId()を使用することはまったく問題ありません。あなたが欲しい:

 db.tweets.find().limit(50).sort({"_id":-1});

これは、ツイートを_id値で降順でソートし、最新の50を取得することを意味します。問題は、現在の結果セットが変化しているときにページネーションが難しいことです。 、結果セットの最小の_id(50番目に新しい_id値)を書き留めてから、次のページを取得します:

 db.tweets.find( {_id : { "$lt" : <50th _id> } } ).limit(50).sort({"_id":-1});

これにより、次の「最新」のツイートが得られます。新しい着信ツイートがページネーションを混乱させることはありません。

_idの値が挿入順序に厳密に対応しているかどうかを心配する必要はまったくありません-99.999%十分に近いため、実際にツイートが最初に来たサブセカンドレベルで誰も気にしません-気づくかもしれませんTwitterは頻繁につぶやきを表示しますが、それほど重要ではありません。

is criticalの場合、同じ手法を使用する必要がありますが、日付は単なる日付ではなく、タイムスタンプである必要がある「日付」を使用します。

56
Asya Kamsky