43

速度を上げるために、クエリを10件の結果に制限したいと思います

db.collection.find( ... ).limit(10)

ただ、総数も知りたいので、「124個あったけど10個しかない」と。これを行うための良い効率的な方法はありますか?

4

6 に答える 6

46

デフォルトでは、クエリ全体の結果をcount()無視しlimit()てカウントします。したがって、たとえばこれを行う場合、var a = db.collection.find(...).limit(10); 実行a.count()するとクエリの総数が得られます。

于 2013-03-08T18:55:53.797 に答える
28

count(1)を実行すると、制限とスキップが含まれます。

于 2014-11-07T17:27:07.277 に答える
7

@johnnycrabが受け入れた回答は、mongoCLIに対するものです。

Node.jsとExpress.jsで同じコードを記述する必要がある場合、toArrayの「結果」とともに「count」関数を使用できるようにするには、このように使用する必要があります。

var curFind = db.collection('tasks').find({query});

次に、このように2つの関数を実行できます(一方が他方にネストされています)

curFind.count(function (e, count) {

// Use count here

    curFind.skip(0).limit(10).toArray(function(err, result) {

    // Use result here and count here

    });

});
于 2016-09-04T21:06:12.833 に答える
5

cursor.count()無視する必要がcursor.skip()ありcursor.limit()、デフォルトで。

ソース:http ://docs.mongodb.org/manual/reference/method/cursor.count/#cursor.count

于 2013-03-08T18:54:46.383 に答える
0

$facet同じ入力ドキュメントのセットで、単一のステージ内で複数の集計パイプラインを処理するステージを使用できます。

// { item: "a" }
// { item: "b" }
// { item: "c" }
db.collection.aggregate([
  { $facet: {
    limit: [{ $limit: 2 }],
    total: [{ $count: "count" }]
  }},
  { $set: { total: { $first: "$total.count" } } }
])
// { limit: [{ item: "a" }, { item: "b" }], total: 3 }

limit: [{ $limit: 2 }]このようにして、同じクエリ内で、いくつかのドキュメント( )とドキュメントの総数()の両方を取得できます{ $count: "count" }

最終ステージは$setオプションのクリーンアップステップであり、$countステージの結果を投影するためにあります。"total" : [ { "count" : 3 } ]total: 3

于 2021-12-03T22:03:11.010 に答える
-1

プッシュとスライスを使用した解決策があります:https ://stackoverflow.com/a/39784851/4752635

私は好みます

  1. 最初にフィルタリングし、次にIDでグループ化して、フィルタリングされた要素の数を取得します。ここではフィルタリングしないでください。不要です。
  2. フィルタリング、並べ替え、ページ分割を行う2番目のクエリ。

$$ROOTをプッシュして$sliceを使用するソリューションでは、大規模なコレクションの場合、ドキュメントメモリの制限が16MBになります。また、大規模なコレクションの場合、2つのクエリを一緒にすると、$$ROOTをプッシュするクエリよりも高速に実行されるようです。それらを並行して実行することもできるので、2つのクエリのうち遅い方(おそらくソートするクエリ)によってのみ制限されます。

私は2つのクエリと集約フレームワークを使用してこのソリューションに落ち着きました(注-この例ではnode.jsを使用していますが、考え方は同じです):

var aggregation = [
  {
    // If you can match fields at the begining, match as many as early as possible.
    $match: {...}
  },
  {
    // Projection.
    $project: {...}
  },
  {
    // Some things you can match only after projection or grouping, so do it now.
    $match: {...}
  }
];


// Copy filtering elements from the pipeline - this is the same for both counting number of fileter elements and for pagination queries.
var aggregationPaginated = aggregation.slice(0);

// Count filtered elements.
aggregation.push(
  {
    $group: {
      _id: null,
      count: { $sum: 1 }
    }
  }
);

// Sort in pagination query.
aggregationPaginated.push(
  {
    $sort: sorting
  }
);

// Paginate.
aggregationPaginated.push(
  {
    $limit: skip + length
  },
  {
    $skip: skip
  }
);

// I use mongoose.

// Get total count.
model.count(function(errCount, totalCount) {
  // Count filtered.
  model.aggregate(aggregation)
  .allowDiskUse(true)
  .exec(
  function(errFind, documents) {
    if (errFind) {
      // Errors.
      res.status(503);
      return res.json({
        'success': false,
        'response': 'err_counting'
      });
    }
    else {
      // Number of filtered elements.
      var numFiltered = documents[0].count;

      // Filter, sort and pagiante.
      model.request.aggregate(aggregationPaginated)
      .allowDiskUse(true)
      .exec(
        function(errFindP, documentsP) {
          if (errFindP) {
            // Errors.
            res.status(503);
            return res.json({
              'success': false,
              'response': 'err_pagination'
            });
          }
          else {
            return res.json({
              'success': true,
              'recordsTotal': totalCount,
              'recordsFiltered': numFiltered,
              'response': documentsP
            });
          }
      });
    }
  });
});
于 2017-02-09T17:46:12.820 に答える