关于Nodejs为什么要用mongoose操作mongodb

关于Nodejs为什么要用mongoose操作mongodb

很多nodejs的新手都是直接用mongodb本身直接操作数据库,我之前也是如此

不知道大家有没有遇到过这个错误: Error: db object already connecting, open cannot be called multiple times

也许你会说是异步写得不好,但是就算异步写得再好,也逃避不了这个错误 因为无论如何,都要用到db.open();这东西,而且访问完毕还得db.close();

于是就有一个问题:刷新得太快,或者多个用户同时访问数据库,数据库没来得及关闭,那个Error就会出现

可以做一下实验,在访问数据库的页面按住F5,就会很容易看到在页面上或者控制台上抛出的Error勒

用mongoose就不会出现这错误勒,因为一旦连接好数据库,db就会处于open状态,不存在访问时要打开,然后又要关闭的规则,然后我果断把所有mongodb部分改为mongoose,按住F5毫无压力啊,而且尼玛代码又短了一大截!

前后代码对比一下:

之前每次操作要open:

User.get = function get(username, callback) {
  mongodb.open(function(err, db) {
    if (err) {
      return callback(err);
    }
    //读取 users 集合
    db.collection('users', function(err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //查找 name 属性为 username 的文档
      collection.findOne({name: username}, function(err, doc) {
        mongodb.close();
        if (doc) callback (err, doc);
        else callback (err, null);
      });
    });
  });
};

现在,建立好mongoose对象模型后只需几行代码即可实现相同的功能:

User.get = function get(username, callback) {
  users.findOne({name:username}, function(err, doc){
    if (err) {
      return callback(err, null);
    }
    return callback(err, doc);
  });
};

23 回复

关于Nodejs为什么要用mongoose操作mongodb

很多Node.js新手在刚开始接触MongoDB时,可能会选择直接使用MongoDB提供的原生驱动程序进行操作。然而,随着时间的推移,你可能会遇到一些问题,例如频繁的数据库连接和断开操作带来的错误。例如:

Error: db object already connecting, open cannot be called multiple times

这个问题的原因在于,每次你需要访问数据库时,都需要手动调用db.open()来打开连接,并在访问完成后调用db.close()来关闭连接。如果刷新得太快或有多个用户同时访问数据库,数据库可能还没来得及关闭,就会导致上述错误。

使用Mongoose的好处

使用Mongoose可以避免这些问题,因为它会自动管理数据库连接。一旦连接成功,数据库就会保持打开状态,直到应用退出。因此,你无需担心多次打开和关闭连接的问题。此外,Mongoose还提供了许多其他便利功能,如数据验证、中间件等。

示例代码对比

原生MongoDB操作

User.get = function get(username, callback) {
  mongodb.open(function(err, db) {
    if (err) {
      return callback(err);
    }
    // 读取 users 集合
    db.collection('users', function(err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      // 查找 name 属性为 username 的文档
      collection.findOne({name: username}, function(err, doc) {
        mongodb.close();
        if (doc) callback(err, doc);
        else callback(err, null);
      });
    });
  });
};

使用Mongoose

User.get = function get(username, callback) {
  users.findOne({name: username}, function(err, doc) {
    if (err) {
      return callback(err, null);
    }
    return callback(err, doc);
  });
};

Mongoose的安装与配置

首先,确保你已经安装了Mongoose:

npm install mongoose

然后,配置Mongoose并连接到MongoDB:

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });

const userSchema = new mongoose.Schema({
  name: String,
  email: String,
  password: String
});

const User = mongoose.model('User', userSchema);

module.exports = User;

通过这种方式,你可以简化代码,提高代码的可维护性和健壮性。希望这些示例代码和解释能帮助你更好地理解为什么在Node.js项目中使用Mongoose操作MongoDB是一个更好的选择。


不知所云

mongo原生的library也可以不close啊

哎呀,我也觉得,既然node.js是单进程的,db何必要close了,一直保持open也不会有太大问题

不太明白您的意思。。具体在nodejs下要怎么搞?

mongoose 不用schema怎么查数据?

有用到schema的,只是没贴上去:

var userObj = new Schema({
  name: {type: String, index: {unique: true}},
  nick: String,
  password: String,
  email: String,
  submit: Number,
  solved: Number,
  regTime: String,
  privilege: String
});

mongoose.model(‘users’, userObj); var users = mongoose.model(‘users’);

对呀,呵呵~

请问如何判断db是否已经Open

User.get = function get(username, callback) { … } 新手问一下 这里的 callback 参数是指什么? 在哪用的? callback 是具体的在哪定义的。 没搞懂mongoose的callback 是指什么? 还是mongo的?

callback是你自己定义的回调函数,用于响应get函数的处理结果,因为get函数是异步的,等get函数出结果了,get函数就调用callback(err, result)

要是用mongodb 需要怎么解决啊

在express3中mogondb一般是怎么用?

自己写mongodb是挺蛋疼的

说到心里去了,曾经的同病相怜者飘过。

node-native-mongodb 要比你所谓的mongoose好用效率几十倍,

mongoose说到底就是纯面向对象和纯关系数据库程序员,一时转换不到动态类型编程的路子上的过渡口而已。

native 的话不要 close 就好了。不过用 mongoose 主要是方便。

楼主不用连接池?每次打开关闭,你想搞死数据库啊😱

请教个问题,db一直open失败,不知道什么原因? 错误打印如下: open err:{ [MongoError: connect UNKNOWN] name: ‘MongoError’, message: ‘connect UNKNOWN’ }

// 源代码如下:

var mongoose = require(‘mongoose’); var mongodb = require(‘mongodb’); var util = require(‘util’);

var server = new mongodb.Server(‘localhost’, 27017, {auto_reconnect:true}); var db = new mongodb.Db(‘account’, server, {safe:true});

db.open(function(err, db){ if (err) { console.log(‘open err:’+ util.inspect(err)); return ; } console.log(‘db opened.’); });

我用 mongo localhost/account命令连接上去,数据库服务都是正常的,但是node.js里就是连接不上,哪位帮我解答一下?

jugglingdb 这个有人用过吗?

深有体会,我用的是connect-mongo模块,当我用压测工具(比如workbench去跑并发的时候),直接就跪了,报错如下:

Error: Can’t set headers after they are sent. at validateHeader (_http_outgoing.js:489:11) at ServerResponse.setHeader (_http_outgoing.js:496:3) at ServerResponse.header (/Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/node_modules/express/lib/response.js:730:10) at ServerResponse.send (/Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/node_modules/express/lib/response.js:170:12) at ServerResponse.json (/Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/node_modules/express/lib/response.js:256:15) at /Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/routes/photo.js:169:36 at /Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/models/post.js:105:24 at Db.collection (/Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/node_modules/mongodb/lib/db.js:466:27) at /Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/models/post.js:102:12 at /Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/node_modules/mongodb/lib/db.js:238:5 at Server.connectHandler (/Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/node_modules/mongodb/lib/server.js:324:7) at Object.onceWrapper (events.js:316:30) at emitOne (events.js:120:20) at Server.emit (events.js:210:7) at /Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/node_modules/mongodb-core/lib/topologies/server.js:300:14 at /Users/xjnotxj/Program/NodeJsProject/PhotoFlowDisplayModule/node_modules/mongodb-core/lib/connection/pool.js:469:18

使用 Mongoose 操作 MongoDB 主要有以下几个原因:

  1. 连接管理:Mongoose 能够自动处理 MongoDB 连接的生命周期,避免了频繁打开和关闭连接的问题。而直接使用 MongoDB 驱动程序时,需要手动管理连接的打开和关闭,这可能导致在高并发情况下出现连接未关闭或重复打开的情况。

  2. 代码简化:Mongoose 提供了更简洁的 API,使得数据库操作变得更加简单和直观。如上面的例子所示,使用 Mongoose 可以省去很多冗余代码,提高了代码的可维护性和可读性。

  3. 数据验证和模式定义:Mongoose 支持定义数据模型(Schema),并且能够进行字段级别的验证,确保数据的正确性和完整性。这对项目的长期维护非常有帮助。

  4. 插件系统:Mongoose 还拥有丰富的插件生态系统,可以方便地扩展功能,比如日志记录、性能监控等。

示例代码

使用 MongoDB 原生驱动

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

User.get = function get(username, callback) {
  mongodb.connect('mongodb://localhost:27017/test', function(err, client) {
    if (err) {
      return callback(err);
    }
    const db = client.db('test');
    const collection = db.collection('users');

    collection.findOne({name: username}, function(err, doc) {
      client.close();
      if (err) {
        return callback(err);
      }
      callback(null, doc);
    });
  });
};

使用 Mongoose

首先安装 Mongoose:

npm install mongoose

然后编写代码:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 定义用户模型
const UserSchema = new Schema({
  name: String,
  email: String
});

const User = mongoose.model('User', UserSchema);

User.get = function get(username, callback) {
  User.findOne({name: username}, function(err, doc) {
    if (err) {
      return callback(err, null);
    }
    callback(null, doc);
  });
};

// 连接到 MongoDB 数据库
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log('Connected to MongoDB'))
  .catch(err => console.error('Failed to connect to MongoDB', err));

通过以上示例可以看出,使用 Mongoose 可以显著简化代码并提高效率。

回到顶部