了不起的NodeJS:MongoDB代码更正

最近在学习NodeJS,在网上一番搜索资料后,很多人都建议读《了不起的NodeJS》,于是就开始开始啃起来了。在一边读一边敲代码的的过程中发现书中有些示例中的代码存在书写或者框架的更新导致运行出错,花了不少时间学习框架的更新和库的使用方法,才让代码运行正常。下面就是有关MongoDB代码更正:

express实例创建

书上的写法

1
var app = express.createServer();

更新后的写法

1
var app = express();

中间件

书上的写法

1
2
3
4
//源代码
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({secret: 'my secret'}));

由于新版的express中将原来自身的大部分中间件都移除了,所以需要额外安装并引用。

1
2
3
4
5
6
7
8
9
//更正后
var session = require('express-session');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(session({secret: 'my secret'}));

bodyParser.urlencoded中的extented设置选项是用来控制POST传递的值是放能被对象化,例如下面的jade模板中input信息

1
input(name="user[first]", type="text")

{ extended: true }: req.body 为 { user: { name: ‘123123’ } }
{ extended: false }: req.body 为 { ‘user[name]’: ‘12313’ }

Jade模板

Jade模板已经更名为Pug,但是仍然可以使用jade。

  1. doctype的变更: doctype 5 => doctype html
  2. 书中index模板中的block body下的代码应该缩进
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //更正后
    extends layout
    block content
    if (authenticated)
    p Welcome back, #{me.first}
    a(href="/logout") Logout
    else
    p Welcome new visitor!
    ul
    li: a(href="/login") Login
    li: a(href="/signup") Signup

mongodb新建collection

1
2
//源代码
app.users = new mongodb.Collection(client, 'users');

这里 Collection 是 mongodb 的方法得用小写,另外在使用 mongodb 之前记得要先用 mongod 命令开启服务器

1
2
//更正后
app.users = new mongodb.collection(client, 'users');

mongodb insert 后的回调使用

1
2
3
4
5
6
//源代码
app.users.insert(req.body.user, function (err, doc) {
if (err) next(err);
console.log(doc);
res.redirect('/login/' + doc[0].email);
});

doc 变成了一个对象,拥有 result 和 ops 两个属性,我们需要的数据在 ops 里面

1
2
3
4
5
app.users.insert(req.body.user, function (err, doc) {
if (err) next(err);
console.log(doc);
res.redirect('/login/' + doc.ops[0].email);
});

204页忘记传 next 了…

1
2
3
4
5
6
7
8
//源代码
app.post('/login', function (req, res) {
app.users.findOne({email: req.body.email, password: req.body.password}, function (err, doc) {
if (err) return next(err);
if (!doc) return res.send('<p>User not found </p>');
req.session.loggedIn = doc._id.toString();
});
});
1
2
3
4
5
6
7
8
//更正后
app.post('/login', function (req, res, next) {
app.users.findOne({email: req.body.email, password: req.body.password}, function (err, doc) {
if (err) return next(err);
if (!doc) return res.send('<p>User not found </p>');
req.session.loggedIn = doc._id.toString();
});
});

mongodb的_id查询

使用 mongodb 的 _id 进行查询,原文中的指代方法已经不能使用了。而 node 本身不提供生成 objectid 的方法这里需要依赖第三方工具

1
2
3
4
5
//源代码
app.users.findOne({_id: {$oid: req.session.loggedIn}}, function (err, doc) {
if (err) return next(err);
next();
});

1
2
3
4
5
6
7
//更正后
var objectid = require('objectid');
app.users.findOne({_id: objectid(req.session.loggedIn)}, function (err, doc) {
if (err) return next(err);
next();
});

jade中全局变量 locals 的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//源代码
app.use(function (req, res, next) {
if (req.session.loggedIn) {
res.local('auth', true);
app.users.findOne({_id: objectid(req.session.loggedIn)}, function (err, doc) {
if (err) return next(err);
res.local('me', doc);
next();
});
} else {
res.local('auth', false);
next();
}
});

这里 express 的定义方法更改了,另外使用 mongodb 查询的时候如果没有查找到并不会报错,而是在回调的 doc 设为 null。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//更正后
app.use(function (req, res, next) {
if (req.session.loggedIn) {
app.locals.auth = true;
app.users.findOne({_id: objectid(req.session.loggedIn)}, function (err, doc) {
if (err) return next(err);
if (doc) app.locals.me = doc;
next();
});
} else {
app.locals.auth = false;
next();
}
});