2013-03-08 7 views

risposta

28

Per impostazione predefinita, count() ignora limit() e conta i risultati di tutta la query. Quindi, quando per esempio fai questo, var a = db.collection.find(...).limit(10); in esecuzione a.count() ti darà il conteggio totale della tua richiesta.

19

Il conteggio (1) include il limite e il salto.

+0

A partire dal mongoengine, 'TypeError: with_limit_and_skip deve essere True o False', count (True) eseguirà il lavoro – kkzxak47

4

La risposta accettata da @johnnycrab è per la CLI mongo.

Se è necessario scrivere lo stesso codice in Node.js e Express.js, sarà necessario utilizzarlo in questo modo per poter utilizzare la funzione "conteggio" insieme al "risultato" di toArray.

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

Quindi è possibile eseguire due funzioni dopo di esso come questo (uno annidato nell'altro)

curFind.count(function (e, count) { 

// Use count here 

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

    // Use result here and count here 

    }); 

}); 
0

c'è una soluzione utilizzando spinta e fetta: https://stackoverflow.com/a/39784851/4752635

ho prefe

  1. Prima di filtrare e quindi raggruppare per ID per ottenere il numero di elementi filtrati. Non filtrare qui, non è necessario.
  2. Seconda query che filtra, ordina e impagina.

La soluzione con spingendo $$ ROOT e utilizzando $ slice viene eseguita nella limitazione della memoria del documento di 16 MB per le raccolte di grandi dimensioni. Inoltre, per le raccolte di grandi dimensioni, due query insieme sembrano essere più veloci di quelle con $$ ROOT push. Puoi eseguirli anche in parallelo, quindi sei limitato solo dal più lento tra le due query (probabilmente quella che ordina).

ho stabilito con questa soluzione con 2 domande e il quadro di aggregazione (nota - io uso node.js in questo esempio, ma l'idea è la stessa):

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

Si prega di non aggiungere [la stessa risposta] (http://stackoverflow.com/a/42143423/4687348) a più domande. Rispondi al migliore e contrassegna il resto come duplicato. Vedi [È accettabile aggiungere una risposta duplicata a diverse domande?] (Http://meta.stackexchange.com/q/104227/347985) – FelixSFD

Problemi correlati