web-dev-qa-db-ja.com

MongoDBで範囲クエリを使用してページ分割を行う方法は?

MongoDBの詳細についてはまだ学んでいるので、おそらく何かが足りないでしょうが、コレクションのページングについてサポートが必要です。

名前のリストがあるコレクションがあります。

牛肉の丸底
鶏の胸肉6oz
鶏の胸肉8oz
鶏の胸肉8oz
鶏の胸肉8oz
鶏の胸肉ランダム
チキンレッグ
チキンテンダーロイン
チキン太もも
コーシャーソルト

「ProductName、_id」に複合インデックスを作成しました。

私はこのクエリを実行します:

db.ProductGuideItem.find( { ProductName: { $gt: "Chicken Breast 8oz" } } ).sort({ProductName:1,_id:1}).limit(3); 

「鶏の胸肉8oz」の商品が3つあることに注意してください。

そのクエリを実行すると、次のようになります...
鶏の胸肉ランダム
チキンレッグ
チキンテンダーロイン

ページングしていて、上から始めた場合。クエリは他の2つの「鶏の胸肉8オンス」を逃していたでしょう。

したがって、各ページに3項目しか含めることができず、ページ2を表示したい場合は、表示する必要があります。
鶏の胸肉8oz
鶏の胸肉8oz
鶏胸肉ランダム。

でも僕はそうじゃない。最後の鶏の胸肉8オンスになり、代わりにそこから始まります。

これを回避する方法はありますか?
また、リストが逆の方法でソートされた場合、どうすればよいですか?

20
Donny V.

ページングしていたコレクションに重複する値があったため、ProductNameとidに複合インデックスを作成する必要がありました。

複合インデックスの作成

db.ProductGuideItem.ensureIndex({ ProductName:1, _id:1});

これは私の問題を解決しました。
参照: https://groups.google.com/d/msg/mongodb-user/3EZZIRJzW_A/oYH79npKZHkJ

これらの値があると仮定します:

{a:1, b:1}
{a:2, b:1}
{a:2, b:2}
{a:2, b:3}
{a:3, b:1}

したがって、範囲ベースのページネーション(ページサイズ2)に対してこれを行います。

1ページ目

find().sort({a:1, b:1}).limit(2)
{a:1, b:1}
{a:2, b:1}

2ページ目

find().min({a:2, b:1}).sort({a:1, b:1}).skip(1).limit(2)

{a:2, b:2}
{a:2, b:3}

3番目のページ

find().min({a:2, b:3}).sort({a:1, b:1}).skip(1).limit(2)
{a:3, b:1}

$ min/maxのドキュメントは次のとおりです。 http://www.mongodb.org/display/DOCS/min+and+max+Query+Specifiers

コレクションに重複する値がない場合は、min&maxを使用したり、複合インデックスを作成したりする必要はありません。 $ ltと$ gtだけを使用できます。

29
Donny V.

カーソルでスキップを呼び出すだけです

cursor skip に関するMongoDBのドキュメントを参照してください。

この例は、Mongodbの example からの引用です。

function printStudents(pageNumber, nPerPage) {
   print("Page: " + pageNumber);
   db.students.find().skip((pageNumber-1)*nPerPage).limit(nPerPage).forEach( function(student) { print(student.name + "<p>"); } );
}
11
moshe beeri