O db.collection não é uma função ao usar o MongoClient v3.0


132

Eu tenho tentado o tutorial do W3schools no nodeJS com o MongoDB.

Quando tento implementar este exemplo em um ambiente nodeJS e invoco a função com uma chamada AJAX, obtive o erro abaixo:

TypeError: db.collection is not a function
    at c:\Users\user\Desktop\Web Project\WebService.JS:79:14
    at args.push (c:\Users\user\node_modules\mongodb\lib\utils.js:431:72)
    at c:\Users\user\node_modules\mongodb\lib\mongo_client.js:254:5
    at connectCallback (c:\Users\user\node_modules\mongodb\lib\mongo_client.js:933:5)
    at c:\Users\user\node_modules\mongodb\lib\mongo_client.js:794:11
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickCallback (internal/process/next_tick.js:104:9)

Por favor, encontre abaixo meu código implementado:

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/mytestingdb";

MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  db.collection("customers").findOne({}, function(err, result) {
    if (err) throw err;
    console.log(result.name);
    db.close();
  });
});

Observe que o erro ocorre sempre que a execução ocorre:

db.collection("customers").findOne({}, function(err, result) {}

Além disso, observe (caso isso importe) que eu instalei o pacote MongoDB mais recente para o nó JS ( npm install mongodb ) e a versão do MongoDB é o MongoDB Enterprise 3.4.4, com o driver MongoDB Node.js v3.0.0-rc0.


Você se certificou de: (1) o banco de dados está sendo executado (dado que não houve erro, acho que sim); (2) o banco de dados mytestingdb existe (tente usar o robomongo / robo3t para acessar sua conexão e ver as coleções) (3) os clientes da coleção realmente existem; Também nos dizer como você está chamando esse script e qual versão do NodeJS (como você instalar?)
nbkhope

O banco de dados e a coleção existem (eu os acessei usando o Studio 3t). Estou depurando o nodeJS chamando o método por meio de uma chamada AJAX, basicamente os pontos de interrupção estão sendo atingidos e tudo funciona bem até que eu receba a exceção mencionada acima. A versão do NodeJS é v6.11.4
Elie Asmar

Em seguida, substitua o código que começa com db.collection()...um log do console para ver se ele chega lá, sem problemas.
Nbkhope

O banco de dados e a coleção existem (eu os acessei usando o Studio 3t). Estou depurando o nodeJS chamando o método por meio de uma chamada AJAX, basicamente os pontos de interrupção estão sendo atingidos e tudo funciona bem até que eu receba a exceção mencionada acima. A versão do NodeJS é v6.11.4
Elie Asmar

Respostas:


80

Eu encontrei a mesma coisa. No package.json, altere a linha do mongodb para "mongodb": "^ 2.2.33". Você precisará npm desinstalar o mongodb; em seguida, npm install para instalar esta versão.

Isso resolveu o problema para mim. Parece ser um bug ou os documentos precisam ser atualizados.


15
verifique a resposta do
MikaS

67
downgrade para uma versão anterior não é realmente uma solução significa apenas que você não se incomodou olhar para as mudanças na API que causaram este
John Culviner

3
@ JohnCulviner - Esse foi um problema de tempo; não é um problema de preguiça. Esse problema ocorreu enquanto eles estavam no processo de lançamento da nova atualização. Eu (e o pôster original) obviamente não percebi isso. Naquele momento, os documentos ainda não estavam atualizados. Eles foram atualizados logo depois. Qualquer pessoa que pretenda resolver isso a partir de agora deve seguir o comentário do MikaS e revisar os documentos atualizados. Fiz o mesmo depois que os documentos foram atualizados e foi possível continuar com a versão atualizada.
AyoO 02/02

1
Agora, encontrei isso - eu estava enfrentando esse problema e tinha o "mongodb:" "3.0.2" instalado no package.json, há problemas com a nova versão?
logos_164

4
Não ajuda em nada. Por que está marcado como a resposta correta?
CodingNow

481

Para pessoas na versão 3.0 do driver NodeJS nativo do MongoDB:

(Isso é aplicável a pessoas com "mongodb": "^ 3.0.0-rc0" ou uma versão posterior no package.json, que desejam continuar usando a versão mais recente.)

Na versão 2.x do driver NodeJS nativo do MongoDB, você obteria o objeto de banco de dados como argumento para o retorno de chamada de conexão:

MongoClient.connect('mongodb://localhost:27017/mytestingdb', (err, db) => {
  // Database returned
});

De acordo com o changelog for 3.0, agora você obtém um objeto cliente que contém o objeto de banco de dados:

MongoClient.connect('mongodb://localhost:27017', (err, client) => {
  // Client returned
  var db = client.db('mytestingdb');
});

O close()método também foi movido para o cliente. O código na pergunta pode, portanto, ser traduzido para:

MongoClient.connect('mongodb://localhost', function (err, client) {
  if (err) throw err;

  var db = client.db('mytestingdb');

  db.collection('customers').findOne({}, function (findErr, result) {
    if (findErr) throw findErr;
    console.log(result.name);
    client.close();
  });
}); 

Agora temos que escrever esta var db = client.db('mytestingdb');linha extra ( ) a cada vez, em vez de apenas escrever assim ( MongoClient.connect('mongodb://localhost:27017/mytestingdb'))? Estou sempre trabalhando com o mesmo banco de dados. Existe alguma abordagem para eliminar essa linha extra? É como uma coisa demorada para mim.
ozgrozer

7
@ozgrozer Parece-me que você está se conectando ao db para cada solicitação. Isso é considerado uma má ideia. Você pode ler sobre isso aqui . Se você se conectar apenas uma vez, haverá apenas uma nova linha por aplicativo que você criar.
Mika Sundland

1
@MikaS Oh sim. Eu estava me conectando ao db como você disse. Eu não sabia que podemos conectar uma vez e reutilizar a variável db. Muito obrigado.
ozgrozer

1
Ótima resposta; descobrir isso foi um tempo chupar, eu deveria lembrar-se de RTFM
Mr.Budris

Eu fiz implementar o cliente como assim, mas ainda existem os mesmos problemas (db.collection não é uma função) dentro \ node_modules \ mongodb \ lib \ GridFS-stream \ index.js: 50: 27
alex351

33

Para aqueles que desejam continuar usando a versão ^ 3.0.1, esteja ciente das mudanças em como você usa o MongoClient.connect()método. O retorno de chamada não dbretorna client, mas retorna , contra o qual existe uma função chamada db(dbname)que você deve chamar para obter a dbinstância que está procurando.

const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');

// Connection URL
const url = 'mongodb://localhost:27017';

// Database Name
const dbName = 'myproject';

// Use connect method to connect to the server
MongoClient.connect(url, function(err, client) {
  assert.equal(null, err);
  console.log("Connected successfully to server");

  const db = client.db(dbName);

  client.close();
});

2
Esta resposta é mais recente e aplica-se à versão 3 do driver. Obrigado
Mohammad

1
Eu recomendo esta solução, é mais apropriada para referência futura.
Jamie Nicholl-Shelley

29
MongoClient.connect(url (err, client) => {
    if(err) throw err;

    let database = client.db('databaseName');

    database.collection('name').find()
    .toArray((err, results) => {
        if(err) throw err;

        results.forEach((value)=>{
            console.log(value.name);
        });
    })
})

O único problema com seu código é que você está acessando o objeto que está segurando o manipulador de banco de dados. Você deve acessar o banco de dados diretamente (consulte a variável de banco de dados acima). Esse código retornará seu banco de dados em uma matriz e, em seguida, passará por ele e registrará o nome de todos os usuários no banco de dados.


Esta resposta é marcada como baixa qualidade devido ao seu comprimento e conteúdo. Forneça mais informações.
Wahyu Kristianto

É apenas o tempo que for necessário. Essa resposta me ajudou.
Manuel Hernandez

1
@ManuelHernandez feliz que ajudou :)
Dre Jackson

este é o ans correto. Marque isso como um ans correto.
Ninad Kambli 19/03

12

Fazendo uma carona na resposta do @MikkaS para o Mongo Client v3.x, eu só precisava do formato async / waitit, que parece um pouco modificado da seguinte forma:

const myFunc = async () => {

     // Prepping here...


    // Connect
    let client = await MongoClient.connect('mongodb://localhost');
    let db = await client.db();

    // Run the query
    let cursor = await db.collection('customers').find({});

    // Do whatever you want on the result.
}

7

Fiz algumas experiências para ver se conseguia manter o nome do banco de dados como parte do URL. Prefiro a sintaxe da promessa, mas ainda deve funcionar para a sintaxe de retorno de chamada. Observe abaixo que client.db () é chamado sem passar nenhum parâmetro.

MongoClient.connect(
    'mongodb://localhost:27017/mytestingdb', 
    { useNewUrlParser: true}
)
.then(client => {

    // The database name is part of the url.  client.db() seems 
    // to know that and works even without a parameter that 
    // relays the db name.
    let db = client.db(); 

    console.log('the current database is: ' + db.s.databaseName);
    // client.close() if you want to

})
.catch(err => console.log(err));

Meu package.json lista o monbodb ^ 3.2.5.

A opção 'useNewUrlParser' não é necessária se você estiver disposto a lidar com um aviso de descontinuação. Mas é aconselhável usar neste momento até a versão 4 ser lançada, onde presumivelmente o novo driver será o padrão e você não precisará mais da opção.


5

Resolvi-o facilmente através da execução desses códigos:

 npm uninstall mongodb --save

 npm install mongodb@2.2.33 --save

Feliz codificação!


4

Eu tenho a versão shell MongoDB v3.6.4, abaixo do código use mongoclient, é bom para mim:

var MongoClient = require('mongodb').MongoClient,
assert = require('assert');
var url = 'mongodb://localhost:27017/video';
MongoClient.connect(url,{ useNewUrlParser: true }, function(err, client) 
{
assert.equal(null, err);
console.log("Successfully connected to server");
var db = client.db('video');
// Find some documents in our collection
db.collection('movies').find({}).toArray(function(err, docs) {
// Print the documents returned
docs.forEach(function(doc) {
console.log(doc.title);
});
// Close the DB
client.close();
});
// Declare success
console.log("Called find()");
 });

Esta questão está relacionada ao driver do nó, não ao shell.
UpTheCreek 25/09

2

Se alguém ainda está tentando resolver esse erro, eu fiz isso como abaixo.

const MongoClient = require('mongodb').MongoClient;
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'mytestingdb';

const retrieveCustomers = (db, callback)=>{
    // Get the customers collection
    const collection = db.collection('customers');
    // Find some customers
    collection.find({}).toArray((err, customers) =>{
        if(err) throw err;
      console.log("Found the following records");
      console.log(customers)
      callback(customers);
    });
}

const retrieveCustomer = (db, callback)=>{
    // Get the customers collection
    const collection = db.collection('customers');
    // Find some customers
    collection.find({'name': 'mahendra'}).toArray((err, customers) =>{
        if(err) throw err;
      console.log("Found the following records");
      console.log(customers)
      callback(customers);
    });
}

const insertCustomers = (db, callback)=> {
    // Get the customers collection
    const collection = db.collection('customers');
    const dataArray = [{name : 'mahendra'}, {name :'divit'}, {name : 'aryan'} ];
    // Insert some customers
    collection.insertMany(dataArray, (err, result)=> {
        if(err) throw err;
        console.log("Inserted 3 customers into the collection");
        callback(result);
    });
}

// Use connect method to connect to the server
MongoClient.connect(url,{ useUnifiedTopology: true }, (err, client) => {
  console.log("Connected successfully to server");
  const db = client.db(dbName);
  insertCustomers(db, ()=> {
    retrieveCustomers(db, ()=> {
        retrieveCustomer(db, ()=> {
            client.close();
        });
    });
  });
});

1

As consultas do MongoDB retornam um cursor para uma matriz armazenada na memória. Para acessar o resultado dessa matriz, você deve chamar .toArray()no final da consulta.

  db.collection("customers").find({}).toArray() 
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.