使用MongoClient v3.0时db.collection不是函数


132

我一直在尝试使用MongoDB在nodeJS上进行W3schools教程

当我尝试在nodeJS环境中实现此示例并通过AJAX调用调用该函数时,出现以下错误:

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)

请在下面找到我的实现代码:

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();
  });
});

请注意,只要执行命中,就会发生错误:

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

另外,请注意(如果有关系的话),我已经为节点JS安装了最新的MongoDB软件包(npm install mongodb),并且MongoDB的版本是MongoDB Enterprise 3.4.4,带有MongoDB Node.js驱动程序v3.0.0-rc0。


您是否确定:(1)数据库正在运行(假设没有错误,我想是这样);(2)数据库mytestingdb存在(尝试使用robomongo / robo3t访问您的连接并查看集合)(3)集合客户实际上存在;还告诉我们您如何调用该脚本以及Nodejs的哪个版本(如何安装?)
nbkhope

数据库和集合存在(我已经使用Studio 3t访问了它们)。我正在通过AJAX调用来调用该方法来调试nodeJS,基本上断点已被击中,并且一切正常,直到出现上述异常。NodeJS版本是v6.11.4
Elie

然后db.collection()...,以控制台日志替换以开头的代码,以查看是否到达那里,没问题。
nbkhope

数据库和集合存在(我已经使用Studio 3t访问了它们)。我正在通过AJAX调用来调用该方法来调试nodeJS,基本上断点已被击中,并且一切正常,直到出现上述异常。NodeJS版本为v6.11.4
Elie

Answers:


80

我遇到了同样的事情。在package.json中,将mongodb行更改为“ mongodb”:“ ^ 2.2.33”。您将需要npm卸载mongodb;然后npm install安装此版本。

这为我解决了这个问题。似乎是错误或文档需要更新。


15
检查MikaS的答案
hartmut

67
降级到较早的版本并不是真正的解决方案,它只是意味着您不必费心研究导致此问题的API更改
John Culviner

3
@JohnCulviner-这是一个时间问题;不是懒惰的问题。他们在发布新更新的过程中发生了此问题。我(和原始海报)显然没有意识到这一点。当时,文档尚未更新。他们在不久之后进行了更新。到目前为止,希望解决此问题的任何人都应遵循MikaS的评论并查看更新的文档。.文档更新后,我也做同样的事情,并且能够继续使用升级版本。
AyoO '18

1
现在遇到这个问题-我遇到了这个问题,并在package.json中安装了“ mongodb:”“ 3.0.2”,新版本是否存在问题?
logos_164

4
完全没有帮助。为什么将其标记为正确答案?
CodingNow

481

对于使用3.0版MongoDB本机NodeJS驱动程序的用户:

(这适用于具有“ mongodb”:“ ^ 3.0.0-rc0”或package.json中更高版本的人,他们想要继续使用最新版本。)

MongoDB本机NodeJS驱动程序的 2.x版中,您将获得数据库对象作为connect回调的参数:

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

根据3.0 的变更日志,您现在将获得一个包含数据库对象的客户端对象:

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

close()方法也已移至客户端。因此,问题中的代码可以转换为:

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();
  });
}); 

现在我们是否必须var db = client.db('mytestingdb');每次都写这行(),而不是像这样写(MongoClient.connect('mongodb://localhost:27017/mytestingdb'))?我一直在使用相同的数据库。有什么方法可以消除多余的线条?对我来说,这有点像耗时的事情。
ozgrozer

7
@ozgrozer对我来说听起来像是您正在为每个请求连接数据库。那被认为是一个坏主意。你可以在这里阅读。如果仅连接一次,则每个创建的应用程序只有一条新线路。
米卡·桑德兰

1
@MikaS哦,是的。我像您说的那样连接到数据库。我不知道我们只能连接一次并重用db变量。非常感谢。
ozgrozer

1
好答案;弄清楚这是一个时间,我应该记得RTFM
Mr.Budris '18

我确实实现了这样的客户端,但是\ node_modules \ mongodb \ lib \ gridfs-stream \ index.js:50:27仍然存在相同的问题(db.collection不是函数)
alex351 '18

33

对于那些想要继续使用版本^ 3.0.1的用户,请注意对使用MongoClient.connect()方法的更改。回调不返回,db而是返回client,针对该回调db(dbname),必须调用一个函数才能获取db要查找的实例。

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
该答案是更新的,并且适用于驱动程序的版本3。谢谢
Mohammad

1
我推荐此解决方案,它更适合将来参考。
Jamie Nicholl-Shelley '18

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);
        });
    })
})

代码的唯一问题是,您正在访问持有数据库处理程序的对象。您必须直接访问数据库(请参见上面的数据库变量)。此代码将以数组形式返回数据库,然后循环遍历该数据库,并记录数据库中每个人的名称。


由于其长度和内容,该答案被标记为低质量。请提供更多信息。
Wahyu Kristianto

只要需要就可以。这个答案帮助了我。
曼努埃尔·埃尔南德斯

1
@ManuelHernandez乐于助人:)
Dre Jackson

这是正确的答案。请将此标记为正确的答案。
Ninad Kambli

12

小猪支持Mongo Client v3.x的@MikkaS答案,我只需要async / await格式,看起来有点修改,如下所示:

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

我做了一些实验,看看是否可以将数据库名称保留为url的一部分。我更喜欢Promise语法,但它仍应适用于回调语法。请注意,在下面的示例中,client.db()的调用没有传递任何参数。

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));

我的package.json列出了monbodb ^ 3.2.5。

如果您愿意处理弃用警告,则不需要'useNewUrlParser'选项。但是明智的做法是在此之前使用第4版,因为新版本可能是默认的新驱动程序,您不再需要该选项。



4

我有MongoDB shell版本v3.6.4,下面的代码使用mongoclient,对我有好处:

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()");
 });

这个问题与节点驱动程序有关,与外壳无关。
UpTheCreek

2

如果有人仍在尝试解决此错误,请按照以下步骤进行操作。

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

MongoDB查询将游标返回到存储在内存中的数组。要访问该数组的结果,必须.toArray()在查询末尾调用。

  db.collection("customers").find({}).toArray() 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.