db.collection no es una función cuando se usa MongoClient v3.0

132

He estado intentando el tutorial de W3schools en nodeJS con MongoDB.

Cuando intento implementar este ejemplo en un entorno nodeJS e invocar la función con una llamada AJAX, recibí el siguiente error:

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)

A continuación encontrará mi 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();
  });
});

Tenga en cuenta que el error ocurre cada vez que la ejecución golpea:

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

Además, tenga en cuenta (en caso de que sea importante) que he instalado el último paquete de MongoDB para el nodo JS ( npm install mongodb ), y la versión de MongoDB es MongoDB Enterprise 3.4.4, con el controlador MongoDB Node.js v3.0.0-rc0.

Elie Asmar
fuente
¿Se aseguró de que: (1) la base de datos se esté ejecutando (dado que no hubo error, supongo que sí); (2) la base de datos mytestingdb existe (intente usar robomongo / robo3t para acceder a su conexión y ver las colecciones) (3) Los clientes de la colección realmente existen; También díganos cómo llama a ese script y qué versión de Nodejs (¿cómo lo instaló?)
nbkhope
La base de datos y la colección existen (he accedido a ellos usando Studio 3t). Estoy depurando nodeJS llamando al método a través de una llamada AJAX, básicamente se están alcanzando los puntos de interrupción y todo funciona bien hasta que obtengo la excepción mencionada anteriormente. La versión de NodeJS es v6.11.4
Elie Asmar
Luego reemplace el código que comienza con db.collection()...un registro de consola para ver si llega allí, no hay problema.
nbkhope
La base de datos y la colección existen (he accedido a ellos usando Studio 3t). Estoy depurando nodeJS llamando al método a través de una llamada AJAX, básicamente se están alcanzando los puntos de interrupción y todo funciona bien hasta que obtengo la excepción mencionada anteriormente. La versión de NodeJS es v6.11.4
Elie Asmar

Respuestas:

80

Encontré lo mismo. En package.json, cambie la línea mongodb a "mongodb": "^ 2.2.33". Deberá desinstalar npm mongodb; luego npm install para instalar esta versión.

Esto resolvió el problema para mí. Parece ser un error o los documentos deben actualizarse.

AyoO
fuente
15
verifique la respuesta de
MikaS
67
degradar a una versión anterior no es realmente una solución, solo significa que no se molestó en buscar los cambios de API que causaron esto
John Culviner
3
@JohnCulviner: este fue un problema de tiempo; No es un problema de pereza. Este problema ocurrió mientras estaban en el proceso de lanzamiento de la nueva actualización. Yo (y el póster original) obviamente no me di cuenta de esto. En ese momento, los documentos aún no estaban actualizados. Fueron actualizados poco después. Cualquier persona que busque resolver esto a partir de ahora debe seguir el comentario de MikaS y revisar los documentos actualizados. Hice lo mismo después de que los documentos se actualizaron y pude continuar con la versión actualizada.
AyoO
1
Al encontrar esto ahora, me encontraba con este problema y tenía el "mongodb:" "3.0.2" instalado en package.json, ¿hay problemas con la nueva versión?
logos_164
44
No ayuda en absoluto. ¿Por qué se marca como la respuesta correcta?
CodingNow
482

Para las personas en la versión 3.0 del controlador NodeJS nativo de MongoDB:

(Esto es aplicable a personas con "mongodb": "^ 3.0.0-rc0", o una versión posterior en package.json, que quieran seguir usando la última versión).

En la versión 2.x del controlador NodeJS nativo de MongoDB , obtendría el objeto de la base de datos como argumento para la devolución de llamada de conexión:

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

De acuerdo con el registro de cambios para 3.0, ahora obtiene un objeto de cliente que contiene el objeto de la base de datos:

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

El close()método también se ha trasladado al cliente. Por lo tanto, el código en la pregunta se puede traducir a:

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();
  });
}); 
Mika Sundland
fuente
¿Ahora tenemos que escribir esta var db = client.db('mytestingdb');línea adicional ( ) cada vez en lugar de simplemente escribir así ( MongoClient.connect('mongodb://localhost:27017/mytestingdb'))? Siempre estoy trabajando con la misma base de datos. ¿Hay algún enfoque para eliminar esa línea extra? Para mí es algo que consume mucho tiempo.
ozgrozer
77
@ozgrozer Me parece que te estás conectando a la base de datos para cada solicitud. Eso se considera una mala idea. Puedes leer sobre esto aquí . Si solo se conecta una vez, solo hay una nueva línea por aplicación que cree.
Mika Sundland
1
@MikaS Oh, sí. Me estaba conectando a la base de datos como dijiste. No sabía que podemos conectarnos una vez y reutilizar la variable db. Muchas gracias.
ozgrozer
1
Gran respuesta; darse cuenta de que esto era una
pérdida de
Implementé el cliente así, pero todavía hay los mismos problemas (db.collection no es una función) dentro de \ node_modules \ mongodb \ lib \ gridfs-stream \ index.js: 50: 27
alex351
34

Para aquellos que desean continuar usando la versión ^ 3.0.1, tenga en cuenta los cambios en la forma en que usa el MongoClient.connect()método. La devolución de llamada no dbregresa client, en cambio, regresa , contra lo cual hay una función llamada db(dbname)que debe invocar para obtener la dbinstancia que está buscando.

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();
});
ra9r
fuente
2
Esta respuesta es más reciente y se aplica a la versión 3 del controlador. Gracias
Mohammad
1
Recomiendo esta solución, es más apropiada para futuras referencias.
Jamie Nicholl-Shelley
31
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);
        });
    })
})

El único problema con su código es que está accediendo al objeto que contiene el manejador de la base de datos. Debe acceder a la base de datos directamente (consulte la variable de base de datos anterior). Este código devolverá su base de datos en una matriz y luego la recorre y registra el nombre de todos en la base de datos.

Dre Jackson
fuente
Esta respuesta está marcada como de baja calidad debido a su longitud y contenido. Por favor proporcione más información.
Wahyu Kristianto
Es solo el tiempo que debe ser. Esta respuesta me ayudó.
Manuel Hernández el
1
@ManuelHernandez me alegra que haya ayudado :)
Dre Jackson
esta es la respuesta correcta Por favor marque esto como una respuesta correcta.
Ninad Kambli
12

Respaldo en la respuesta @MikkaS para Mongo Client v3.x, solo necesitaba el formato asíncrono / espera, que se ve ligeramente modificado como este:

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.
}
agarcian
fuente
7

Experimenté un poco para ver si podía mantener el nombre de la base de datos como parte de la URL. Prefiero la sintaxis de promesa, pero aún debería funcionar para la sintaxis de devolución de llamada. Observe a continuación que se llama a client.db () sin pasar ningún 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));

Mi package.json enumera monbodb ^ 3.2.5.

La opción 'useNewUrlParser' no es necesaria si está dispuesto a lidiar con una advertencia de desaprobación. Pero es aconsejable usar en este punto hasta que salga la versión 4, donde presumiblemente el nuevo controlador será el predeterminado y ya no necesitará la opción.

pwilcox
fuente
5

Lo resolví fácilmente ejecutando estos códigos:

 npm uninstall mongodb --save

 npm install mongodb@2.2.33 --save

¡Feliz codificación!

Saurabh Singh
fuente
4

Tengo la versión de shell MongoDB v3.6.4, debajo del código uso mongoclient, es bueno para mí:

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()");
 });
Gianluca Mazzeo
fuente
Esta pregunta se refiere al controlador de nodo, no al shell.
UpTheCreek
3

Si alguien todavía está intentando resolver este error, lo he hecho a continuación.

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();
        });
    });
  });
});
Mahendra Bagul
fuente
Esta solución y la de @Dre Jackson son las que funcionan con el nodo a partir del 07/2020. Parece que lo que se pasa como argumento para la devolución de llamada de conexión es el MongoClient en lugar de un db, por lo que debe obtener el db de él. Aparte de eso, esta solución también enumera useUnifiedTopology: true, que también se necesita en la actualidad.
Coffee_fan hace
1

Las consultas MongoDB devuelven un cursor a una matriz almacenada en la memoria. Para acceder al resultado de esa matriz, debe llamar .toArray()al final de la consulta.

  db.collection("customers").find({}).toArray() 
pmpc2
fuente