sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB - Aggregation Framework (totalt antal)

Det finns en lösning med push and skiva:https://stackoverflow.com/a/39784851/4752635 (@emaniacs nämner det här också).

Men jag föredrar att använda 2 frågor. Lösning med att trycka på $$ROOT och använda $slice körs in i dokumentminnesbegränsning på 16MB för stora samlingar. För stora samlingar verkar två frågor tillsammans köra snabbare än den med $$ROOT-pushing. Du kan köra dem parallellt också, så du begränsas endast av den långsammare av de två frågorna (förmodligen den som sorterar).

  1. Först för att filtrera och sedan gruppera efter ID för att få antalet filtrerade element. Filtrera inte här, det är onödigt.
  2. Andra fråga som filtrerar, sorterar och sidnumrerar.

Jag har gjort upp med den här lösningen med två frågor och aggregeringsramverk (obs - jag använder node.js i det här exemplet):

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
            });
          }
      });
    }
  });
});


  1. Hur du övervakar dina databasservrar med ClusterControl CLI

  2. Mongodb sorterar med skiftlägesokänsligt sätt

  3. Hur man säkrar MongoDB med användarnamn och lösenord

  4. Körande meteor i ett kluster och förändringar i realtid