web-dev-qa-db-ja.com

集約フレームワークの$ skipと$ limit

この文書を読んだとき、次のメモを見つけました。

パイプラインで$ sortが$ limitの直前にある場合、$ sort操作は進行中に上位n個の結果のみを保持します。nは指定された制限で、MongoDBはメモリにn個のアイテムを保存するだけです。この最適化は、allowDiskUseがtrueで、n個のアイテムが集約メモリの制限を超える場合にも適用されます。

これについて正しい場合は、$ sortと$ limitを一緒に使用する場合にのみ適用されます

db.coll.aggregate([
    ...,
    {$sort: ...},
    {$limit: limit},
    ...
]);

ただし、ほとんどの場合、

db.coll.aggregate([
    ...,
    {$sort: ...},
    {$skip: skip},
    {$limit: limit},
    ...
]);

質問1:ここで$ skipを使用すると、上記のルールが適用されないということですか?

理論的には、MongoDBは依然として上位nレコードを計算し、上位nレコードのみをソートすることでパフォーマンスを向上できるため、この質問をします。しかし、これに関するドキュメントは見つかりませんでした。ルールが適用されない場合、

質問2:パフォーマンスを向上させるには、クエリを次のように変更する必要がありますか?

db.coll.aggregate([
    ...,
    {$sort: ...},
    {$limit: skip + limit},
    {$skip: skip},
    {$limit: limit},
    ...
]);

[〜#〜] edit [〜#〜]:私のユースケースでは、上記の質問がより理にかなっていると説明すると思います。 MongoDB 2.6が提供するテキスト検索機能を使用して製品を探しています。ユーザーが「赤」のような非常に一般的なキーを入力すると、返される結果が多すぎるのではないかと心配しています。したがって、この結果を生成するより良い方法を探しています。

EDIT2:上記の最後のコードは次と等しいことがわかります

db.coll.aggregate([
    ...,
    {$sort: ...},
    {$limit: skip + limit},
    {$skip: skip},
    ...
]);

したがって、常にこのフォームを使用してtop nルールを適用できます。

35
yaoxing

これはテキスト検索クエリであるため、最も最適な形式は次のとおりです。

db.collection.aggregate([
    { "$match": {
        "$text": { "$search": "cake tea" }
    }},
    { "$sort": { "score": { "$meta": "textScore" } },
    { "$limit": skip + limit },
    { "$skip": skip }
])

上位の「ソート」結果からのメモリ予約の理論的根拠は、本来の「制限」内でのみ機能し、これはデータのいくつかの妥当な「ページ」を超えるものには最適ではありません。

メモリの消費が合理的な範囲を超えると、追加のステージはポジティブではなくネガティブな効果を持つ可能性があります。

これらは、現在の形式でMongoDBが使用できるテキスト検索機能の実際的な制限です。しかし、より詳細でより多くのパフォーマンスが必要な場合は、多くのSQL「フルテキスト」ソリューションの場合と同様に、外部の「専用」テキスト検索ソリューションを使用することをお勧めします。

49
Neil Lunn