2012-12-18 10 views
50

クエリパフォーマンス上の奇妙なビット...私は、ドキュメントの総数を行うクエリを実行する必要がありますまた、制限され、オフセットすることができます結果セットを返すことができます。マングース制限/オフセットとカウントクエリ

だから、最初にすべての57件の文書のクエリ(配列として返さ)があり、私は合計で57件の文書を持っており、ユーザーは、私がこれを行うための2つの方法を考えることができる20

によってオフセット10件の文書を望んでいますarray.sliceを使用して、必要なドキュメントを返します。 2番目のオプションは、mongoのネイティブ 'count'メソッドを使用する最初の2つのクエリを実行し、mongoのネイティブ$ limitおよび$ skipアグリゲータを使用して2番目のクエリを実行することです。

拡大率はどれくらいになると思いますか? 1つのクエリですべてを実行するか、2つのクエリを別々に実行しますか?

編集:

// 1 query 
var limit = 10; 
var offset = 20; 

Animals.find({}, function (err, animals) { 
    if (err) { 
     return next(err); 
    } 

    res.send({count: animals.length, animals: animals.slice(offset, limit + offset)}); 
}); 


// 2 queries 
Animals.find({}, {limit:10, skip:20} function (err, animals) {    
    if (err) { 
     return next(err); 
    } 

    Animals.count({}, function (err, count) { 
     if (err) { 
      return next(err); 
     } 

     res.send({count: count, animals: animals}); 
    }); 
}); 
+0

私はMongooseについては確信していますが、PHPのデフォルトの 'count()'関数は、limitとskipの1つのクエリを実行してカウントを取得するように指示されていない限り、 'limit'または' skip'を考慮しませんおそらく最も性能の高いソリューションです。しかし、そこにあるものを数えるために2つのクエリを実行しないと、どのようにして57個のドキュメントがありますか?あなたは変わらない静的な数字を持っていますか?そうでない場合は、スキップしてからカウントを制限する必要があります。 – Sammaye

+0

申し訳ありません、Mongoのネイティブカウントメソッド 'db.collection.find().count();' – leepowell

+0

を使用しています。申し訳ありませんが、私はあなたの質問を誤解しました。うーん、実際には、どちらが良いだろうか分からない、57 docsのように常にあなたの結果セットは本当に低いでしょうか?そうであれば、クライアント側のスライスは1分の1になります。 – Sammaye

答えて

76

は、私はあなたが2つのクエリを使用することをお勧め:

  1. db.collection.count()は、項目の合計数を返します。この値はMongoのどこかに保存され、計算されません。

  2. db.collection.find().skip(20).limit(10)ここでは、一部のフィールドで並べ替えを使用できると仮定しているため、このフィールドにインデックスを追加することを忘れないでください。このクエリも高速になります。

私はあなたがビッグデータを持っている場合、後であなたが転送し、処理データに問題があるだろう引き起こし、あなたはすべての項目を照会して、スキップを行うと取るよりべきではないと思います。

+0

私が書いているのは、単なるコメントではありませんが、 '.skip()'命令はCPUのために重いと聞いたことがあります。これは、コレクションの先頭に移動し、パラメータで指定された値.skip()のそれは大きなコレクションに本当の影響を与えることができます! しかし、私はどちらを使うのが最も重いのか分かりません。とにかく.skip()とか、コレクション全体を取得してJSでトリミングしてみてください...どう思いますか? –

+1

@Stuffix私は '.skip()'を使うことと同じ懸念を聞いてきました。この[回答](http://stackoverflow.com/questions/5539955/how-to-paginate-with-mongoose-in-node-js/23640287#23640287)に触れ、日付フィールド。これを '.skip()'と '.take()'メソッドで使うことができます。これは良い考えのようです。しかし、このOPの質問には、合計の文書数を取得する方法に問題があります。フィルタが '.skip()'のパフォーマンスの影響に対処するために使用されている場合、正確なカウントはどのようにして得られますか? dbに格納されたカウントには、フィルタされたデータセットが反映されません。 –

+0

こんにちは@MichaelLeanos、私は同じ問題に直面しています:すなわち、どのように合計ドキュメントの数を取得する。フィルタが使用されている場合、正確なカウントはどのようにして得られますか? これには解決策がありましたか? – virsha

0

この問題に自分自身で対処した後、私はuser854301の回答に基づいて構築したいと考えています。

Mongoose^4.13.8 toConstructor()という関数を使用すると、フィルタを適用したときにクエリを複数回構築することを避けることができました。私はこの機能が古いバージョンでも利用可能であることを知っていますが、これを確認するにはMongooseのドキュメントをチェックする必要があります。

以下は、ブルーバードの約束を使用しています。

let schema = Query.find({ name: 'bloggs', age: { $gt: 30 } }); 

// save the query as a 'template' 
let query = schema.toConstructor(); 

return Promise.join(
    schema.count().exec(), 
    query().limit(limit).skip(skip).exec(), 

    function (total, data) { 
     return { data: data, total: total } 
    } 
); 

今カウントクエリは、それがマッチした総レコードを返され、返されたデータは、全レコードのサブセットになります。

クエリを構成するquery()を中心に()に注意してください。

関連する問題