¿Cómo obtener todo el recuento del modelo de mangosta?

101

¿Cómo puedo saber el recuento de un modelo cuyos datos se han guardado? hay un método de Model.count(), pero no parece funcionar.

var db = mongoose.connect('mongodb://localhost/myApp');
var userSchema = new Schema({name:String,password:String});
userModel =db.model('UserList',userSchema);        
var userCount = userModel.count('name');

userCountes un objeto, ¿qué método llamado puede obtener un real count?

Gracias

smilexu
fuente
1
Si está utilizando ES 2016, puede ajustar la llamada para contar dentro de una promesa y llamarla con un generador.
mikeyGlitz

Respuestas:

125

El siguiente código funciona. Tenga en cuenta el uso de countDocuments .

 var mongoose = require('mongoose');
 var db = mongoose.connect('mongodb://localhost/myApp');
 var userSchema = new mongoose.Schema({name:String,password:String});
 var userModel =db.model('userlists',userSchema);
 var anand = new userModel({ name: 'anand', password: 'abcd'});
 anand.save(function (err, docs) {
   if (err) {
       console.log('Error');
   } else {
       userModel.countDocuments({name: 'anand'}, function(err, c) {
           console.log('Count is ' + c);
      });
   }
 }); 
almypal
fuente
150

La razón por la que su código no funciona es porque la función de recuento es asincrónica, no devuelve un valor sincrónicamente.

Aquí hay un ejemplo de uso:

userModel.count({}, function( err, count){
    console.log( "Number of users:", count );
})
Hasta el arroyo
fuente
Dame un ejemplo para obtener el método de conteo sincrónico
sankar muniyappa
Lo mismo para mi. Estoy buscando lo mismo
nowox
11
countEl método está depricado, puede usar la countDocumentsmisma sintaxis
Kir Novak
@KirNovak Gracias hermano. También proporcioné la URL en mangosta para la desaprobación .
Tes3awy
25

Collection.count está obsoleto y se eliminará en una versión futura. Usar colección. countDocuments o colección. EstimatedDocumentCount en su lugar.

userModel.countDocuments(query).exec((err, count) => {
    if (err) {
        res.send(err);
        return;
    }

    res.json({ count: count });
});
Benjamín
fuente
3
aquí está el enlace de documentación: mongoosejs.com/docs/api.html#model_Model.estimatedDocumentCount
babar78
Tuve el problema de que en nuestro proyecto una rutina de configuración prueba los elementos existentes en cualquier colección. El método count () se comportó de manera extraña: cuando la colección no estaba vacía, a veces no devolvía nada (indefinido, nulo, cero o falso; no pudimos investigar más). Todavía no averiguamos qué causó el problema ya que era una condición de carrera que sucedía muy raramente. El uso de countDocuments ({}) ahora funciona para nosotros. ¡Gracias!
ha110_b1mm3lbahn
UnhandledPromiseRejectionWarning: TypeError: userModel.countDocuments is not a function¿Recibo un error al usarlo en mi propio modelo de usuario?
Luke Brown
¿Cómo podemos hacer que "userModel.countDocuments" sea una llamada sincrónica para que pueda agregar un virtual al esquema que agregue algo de "clave y valor" en mi documento?
Satyam
25

Deberías dar un objeto como argumento

userModel.count({name: "sam"});

o

userModel.count({name: "sam"}).exec(); //if you are using promise

o

userModel.count({}); // if you want to get all counts irrespective of the fields

En la versión reciente de mangosta, count () está en desuso, así que use

userModel.countDocuments({name: "sam"});
Moh .S
fuente
2
DeprecationWarning: collection.count está en desuso, debe usar .estimatedDocumentCount () o .countDocuments () en su lugar.
HMagdy
9

Antecedentes de la solución

Como se indica en la documentación de mangosta y en la respuesta de Benjamin, el método Model.count()está en desuso. En lugar de utilizar count(), las alternativas son las siguientes:

Model.countDocuments(filterObject, callback)

Cuenta cuántos documentos coinciden con el filtro en una colección. Pasar un objeto vacío {} como filtro ejecuta un escaneo de colección completo. Si la colección es grande, se puede utilizar el siguiente método.

Model.estimatedDocumentCount()

Este método de modelo estima el número de documentos de la colección MongoDB. Este método es más rápido que el anterior countDocuments(), porque utiliza metadatos de colección en lugar de pasar por toda la colección. Sin embargo, como sugiere el nombre del método, y dependiendo de la configuración de la base de datos, el resultado es una estimación, ya que es posible que los metadatos no reflejen el recuento real de documentos en una colección en el momento de ejecución del método.

Ambos métodos devuelven un objeto de consulta mongoose, que se puede ejecutar de una de las dos formas siguientes. Úselo .exec()si desea ejecutar una consulta más adelante.

La solución

Opción 1: pasar una función de devolución de llamada

Por ejemplo, cuente todos los documentos de una colección usando .countDocuments():

someModel.countDocuments({}, function(err, docCount) {
    if (err) { return handleError(err) } //handle possible errors
    console.log(docCount)
    //and do some other fancy stuff
})

O cuente todos los documentos de una colección que tengan un nombre determinado utilizando .countDocuments():

someModel.countDocuments({ name: 'Snow' }, function(err, docCount) {
    //see other example
}

Opción 2: usar .then()

Una consulta de mangosta tiene .then()por lo que es "thenable". Esto es por conveniencia y la consulta en sí no es una promesa.

Por ejemplo, cuente todos los documentos de una colección usando .estimatedDocumentCount():

someModel
    .estimatedDocumentCount()
    .then(docCount => {
        console.log(docCount)
        //and do one super neat trick
    })
    .catch(err => {
        //handle possible errors
    })

Opción 3: usar async / await

Cuando se usa el enfoque asíncrono / espera, la forma recomendada es usarlo con .exec()ya que proporciona mejores seguimientos de pila.

const docCount = await someModel.countDocuments({}).exec();

Aprendiendo por stackoverflowing,

heilala
fuente
1

Las respuestas más votadas aquí están perfectamente bien, solo quiero agregar el uso de await para que la funcionalidad solicitada se pueda archivar:

const documentCount = await userModel.count({});
console.log( "Number of users:", documentCount );

Se recomienda usar countDocuments () sobre 'count ()', ya que quedará obsoleto. Entonces, por ahora, el código perfecto sería:

const documentCount = await userModel.countDocuments({});
console.log( "Number of users:", documentCount );
Mridul Tripathi
fuente
-1

Como se dijo antes, el código no funcionará como está. Una solución sería usar una función de devolución de llamada, pero si cree que lo llevaría a un 'infierno de devolución de llamada', puede buscar "Promesas".

Una posible solución usando una función de devolución de llamada:

//DECLARE  numberofDocs OUT OF FUNCTIONS
     var  numberofDocs;
     userModel.count({}, setNumberofDocuments); //this search all DOcuments in a Collection

si desea buscar la cantidad de documentos en función de una consulta, puede hacer esto:

 userModel.count({yourQueryGoesHere}, setNumberofDocuments);

setNumberofDocuments es una función separada:

var setNumberofDocuments = function(err, count){ 
        if(err) return handleError(err);

        numberofDocs = count;

      };

Ahora puede obtener la cantidad de documentos en cualquier lugar con una función getFunction:

     function getNumberofDocs(){
           return numberofDocs;
        }
 var number = getNumberofDocs();

Además, usa esta función asincrónica dentro de una sincrónica usando una devolución de llamada, ejemplo:

function calculateNumberOfDoc(someParameter, setNumberofDocuments){

       userModel.count({}, setNumberofDocuments); //this search all DOcuments in a Collection

       setNumberofDocuments(true);


} 

Espero que pueda ayudar a otros. :)

AndBecaPine
fuente
En la función calculateNumberOfDoc (), ¿por qué llamas a setNumberofDocuments (true)? ¿No produciría un error primero, incluso antes de que se devuelva el recuento real?
pravin