CNode

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

Kkimady发布于14 年前最后回复9 年前27 回复73385 浏览0 收藏

很多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);
  });
};
查看回复

回复 (27)

C
chenkline#1·11 年前

请教个问题,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里就是连接不上,哪位帮我解答一下?

Y
yakczh#2·11 年前

jugglingdb 这个有人用过吗?

X
xjnotxj#3·9 年前

深有体会,我用的是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

K
kimady#4·14 年前
引用 ltebeanmongo原生的library也可以不close啊

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

P
philsong#5·14 年前

不知所云

L
ltebean#6·14 年前

mongo原生的library也可以不close啊

S
saber#7·14 年前

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

X
xiongliding#8·14 年前
引用 ltebeanmongo原生的library也可以不close啊

@kimady 举一种最简单的做法:把 mongodb.open 写在最外围

mongodb.open(function(err, db) {
  // 把所有其他代码都包含在这个里面,并且丢掉 mongodb,只使用 db
});
K
kimady#9·14 年前
引用 ltebeanmongo原生的library也可以不close啊

@XiongLiding 哦,但是我那个项目东西有点多,用的是express,这样做的话全部都挤到一起了不太好吧?而且好像挺难弄的~

Y
yakczh#10·14 年前

mongoose 不用schema怎么查数据?

K
kimady#11·14 年前
引用 yakczhmongoose 不用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');
L
ltebean#13·14 年前
引用 ltebeanmongo原生的library也可以不close啊

@kimady 还有原生的libray每步操作都是回调方法,嵌套会很多,可以用step或者async做control flow,代码看上去会舒服很多~

K
kimady#14·14 年前
引用 ltebeanmongo原生的library也可以不close啊

@ltebean 谢谢你哈,我慢慢看:)

P
prophet#16·13 年前

要是用mongodb 需要怎么解决啊

Y
yakczh#17·13 年前
引用 prophet要是用mongodb 需要怎么解决啊

在express3中mogondb一般是怎么用?

Z
zhishaofei3#18·12 年前

自己写mongodb是挺蛋疼的

A
AdamsMao#19·12 年前

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

T
tulayang#20·12 年前

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

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

X
XadillaX#21·12 年前

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

N
ngot#22·12 年前

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

H
happyfire#23·13 年前

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

J
jinwyp#24·13 年前

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

Z
zensh#25·13 年前
引用 jinwypUser.get = function get(username, callback) { ... } 新手问一下 这里的 callback 参数是指什么? 在哪用的? callback 是具...

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

S
sumory#27·13 年前
参与回复
登录后即可参与回复。登录