Como obter todas as contagens do modelo de mangusto?


101

Como posso saber a contagem de um modelo cujos dados foram salvos? existe um método de Model.count(), mas não 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');

userCounté um objeto, qual método chamado pode obter um real count?

obrigado


1
Se você estiver usando o ES 2016, pode encerrar a chamada para contar dentro de uma promessa e chamá-la com um gerador.
mikeyGlitz de

Respostas:


125

O código abaixo funciona. Observe o 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);
      });
   }
 }); 

150

O motivo pelo qual seu código não funciona é porque a função de contagem é assíncrona, ela não retorna um valor de forma síncrona.

Aqui está um exemplo de uso:

userModel.count({}, function( err, count){
    console.log( "Number of users:", count );
})

Dê-me um exemplo para obter o método de contagem síncrona
sankar muniyappa

O mesmo para mim. Estou procurando o mesmo
agora

11
countmétodo está obsoleto, você pode usar a countDocumentsmesma sintaxe
Kir Novak

@KirNovak Obrigado mano. Eu também forneci o url em mongoose para a suspensão de uso .
Tes3awy

25

O collection.count está obsoleto e será removido em uma versão futura. Use a coleção. countDocuments ou coleção. estimadoDocumentCount em vez disso.

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

    res.json({ count: count });
});


Eu tive o problema, que em nosso projeto uma rotina de configuração de testes para itens existentes em qualquer coleção. O método count () se comportou de forma estranha: quando a coleção não estava vazia, às vezes não retornava nada (indefinido, nulo, zero ou falso - não poderíamos investigar mais). Ainda não descobrimos o que causou o problema, pois era uma condição de corrida que acontecia muito raramente. Usar countDocuments ({}) agora funciona para nós. Obrigado!
ha110_b1mm3lbahn

UnhandledPromiseRejectionWarning: TypeError: userModel.countDocuments is not a functionRecebo um erro ao usá-lo em meu próprio userModel?
Luke Brown,

Como podemos fazer "userModel.countDocuments" como uma chamada síncrona para que eu possa adicionar um virtual ao esquema que adiciona alguma "chave e valor" em meu documento.
Satyam

25

Você deve dar um objeto como argumento

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

ou

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

ou

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

Na versão recente do mongoose, count () está obsoleto, então use

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

2
DeprecationWarning: collection.count está obsoleto, você deve usar .estimatedDocumentCount () ou .countDocuments () em seu lugar.
HMagdy

9

Antecedentes para a solução

Conforme declarado na documentação do mangusto e na resposta de Benjamin, o método Model.count()está obsoleto. Em vez de usar count(), as alternativas são as seguintes:

Model.countDocuments(filterObject, callback)

Conta quantos documentos correspondem ao filtro em uma coleção. Passar um objeto vazio {} como filtro executa uma verificação de coleção completa. Se a coleção for grande, o método a seguir pode ser usado.

Model.estimatedDocumentCount()

Este método de modelo estima o número de documentos na coleção MongoDB. Este método é mais rápido que o anterior countDocuments(), porque usa metadados de coleção em vez de percorrer toda a coleção. No entanto, como o nome do método sugere, e dependendo da configuração do banco de dados, o resultado é uma estimativa, pois os metadados podem não refletir a contagem real de documentos em uma coleção no momento da execução do método.

Ambos os métodos retornam um objeto de consulta mongoose, que pode ser executado de uma das seguintes maneiras. Use .exec()se quiser executar uma consulta posteriormente.

A solução

Opção 1: passe uma função de retorno de chamada

Por exemplo, conte todos os documentos em uma coleção usando .countDocuments():

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

Ou conte todos os documentos em uma coleção com um determinado nome usando .countDocuments() :

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

Opção 2: usar .then()

Uma consulta de mangusto tem .then() é "thenable". Isso é para conveniência e a consulta em si não é uma promessa.

Por exemplo, conte todos os documentos em uma coleção usando .estimatedDocumentCount():

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

Opção 3: usar assíncrono / esperar

Ao usar a abordagem async / await, a maneira recomendada é usá-la com, .exec()pois ela fornece rastreamentos de pilha melhores.

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

Aprendendo pelo overflowing da pilha,


1

As respostas com maior votação aqui estão perfeitamente bem. Eu só quero adicionar o uso de await para que a funcionalidade solicitada possa ser arquivada:

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

É recomendado usar countDocuments () em vez de 'count ()', pois será obsoleto a partir de agora. Então, por enquanto, o código perfeito seria:

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

-1

Como disse antes, seu código não funcionará do jeito que está. Uma solução para isso seria usar uma função de retorno de chamada, mas se você acha que isso o levaria a um 'inferno de retorno de chamada', você pode pesquisar por "Promessas".

Uma possível solução usando uma função de retorno de chamada:

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

se quiser pesquisar o número de documentos com base em uma consulta, você pode fazer o seguinte:

 userModel.count({yourQueryGoesHere}, setNumberofDocuments);

setNumberofDocuments é uma função separada:

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

        numberofDocs = count;

      };

Agora você pode obter o número de documentos em qualquer lugar com um getFunction:

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

Além disso, você usa esta função assíncrona dentro de uma função síncrona usando um retorno de chamada, por exemplo:

function calculateNumberOfDoc(someParameter, setNumberofDocuments){

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

       setNumberofDocuments(true);


} 

Espero que possa ajudar outras pessoas. :)


Na função CalculeNumberOfDoc (), por que você está chamando setNumberofDocuments (true)? Isso não resultaria em erro primeiro, mesmo antes de a contagem real ser retornada ??
pravin
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.