写一个Node项目需要用到MongoDB,ExpressNode,于是翻译了这篇博客. 介绍了MongoDB和mongoose的搭配使用,和在Node环境中管理数据库的过程.

原文请见 Easily Develop Node.js and MongoDB Apps with Mongoose

前言

Node.js 和 MongoDB 是天造地设的一对. MongoDB 跨越数据库和 Javascript,随意使用 JSON 的特性,使得开发过程变得非常容易. 这也是为什么会有 MEAN 这样的架构出现的原因,MEAN 架构正是指采用了 Node, Express, MongoDB, AngularJS 的技术栈.

CRUD 是目前大多数应用开发所必要的部分,我们随时都需要需要创建,读取,更新,删除数据.

下面我们将通过一些代码片段了解一下在 Node.js, ExpressJS 和 MongoDB 中该如何处理 CRUD. 我们还将使用到一个常用的 Node 库: mongoose

我们使用 CRUD 函数写出的 API, 常常也被称为 Node.js RESTful API. 读完这篇文章,你将了解实际代码长什么样. 这篇文章介绍了 mongoose 的多种命令和它们的用法.

什么是 Mongoose?

mongoose 是一个 Node 中的对象建模工具,跟其它语言中的 ORM 类似(比如 Eloquent for Laravel).

mongoose 让我们能简单方便的连接到 MongoDB 进行 CRUD 操作. 首先我们要安装好 mongoose,然后才能开始使用.

1
$ npm install mongoose --save

已经安装好 mongoose,我们再在自己的项目中引入它.

1
var mongoose = require('mongoose');

我们还需要连接到 MongoDB 数据库(不管是本地的还是远程的)

1
mongoose.connect('mongodb://localhost/myappdatabase');

下面我们开始正式使用.

模型的定义(Model

在我们处理 CRUD 操作之前,需要建立好 mongoose 模型(mongoose Model). 这些模型将作为我们定义的数据结构的构造函数. 它们表示了可以从数据库保存和检索的文档(document)的结构.

Mongoose Schema mongoose schema 定义了文档属性,主要是键和键值的类型.

Mongoose Methods (除了自带的方法),自定义方法也可以被定义到 mongoose schema 中.

例子:Users 模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 引入要用到的JS模块
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// 创建 schema
var userSchema = new Schema({
name: String,
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
admin: Boolean,
location: String,
meta: {
age: Number,
website: String
},
created_at: Date,
updated_at: Date
});

// 现在的 schema 还是没什么用的
// 我们还需要在它的基础上创建一个模型 (model)
var User = mongoose.model('User', userSchema);

// 导出我们之前定义好的 user model
module.exports = User;

这就是创建 Schema 的方式. 首先要引入 mongoose 和 mongoose.schema 库. 然后在 userSchema 中定义 user 数据的属性. 另外要提的一点是我们可以定义嵌套的数据结构,就像例子中的meta属性那样.

mongodb 支持的数据类型(SchemaTypes)有:

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array

然后我们调用 mongoose.model 创建一个 mongoose 模型. 同样,我们还可以定义很多其它的方法,比如定义一个密码加密算法等等.

自定义方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 注释和上段代码重复的部分省略
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// 此处省略号省略部分和上一段代码中这部分相同
var userSchema ...

// 自定义一个方法,该方法在用户名后面加上一个字符串
// 你还可以定义很多重要的方法,比如用户名安全检测或者是格式化
// 你还可以进行查询,查询类似用户等等
userSchema.methods.dudify = function() {
this.name = this.name + '-dude';

return this.name;
};

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

module.exports = User;

使用实例

现在我们有了自定义模型和方法,我们可以在自己的代码中调用它们.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 假设 user.js 文件位于 app/models/ 目录下
var User = require('./app/models/user');

// 创建一个新用户,名字是 chris
var chris = new User({
name: 'Chris',
username: 'sevilayha',
password: 'password'
});

// 调用自定义方法. 在原名后面加上 '-dude'
// 最终用户名会是 Chris-dude
chris.dudify(function(err, name) {
if (err) throw err;

console.log('Your new name is ' + name);
});

// 调用 mongoose 自带的 save 方法,将数据保存到数据库
chris.save(function(err) {
if (err) throw err;

console.log('User saved successfully!');
});

这个例子虽然没有任何实用性,但是创建和使用自定义方法的方式却是通用的. 用类似的步骤,我们可以在保存之前对用户密码使用 hash 方法处理,对比密码等等.

在保存之前运行一个函数

假如我们还需要保存数据创建的时间 created_at,我们可以添加一个 pre 方法,用它把将要保存的数据进行一些预先处理.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 在每次保存之前,添加一个 date 属性
userSchema.pre('save', function(next) {
// 获取当前时间
var currentDate = new Date();

// 把 updated_at 更新到当前时间
this.updated_at = currentDate;

// 如果 created_at 不存在,同样把它添加进去
if (!this.created_at)
this.created_at = currentDate;

next();
});

现在每次保存时,date 都会得到更新. 对密码进行 hash 或者 salt 处理跟这个类似,永远也别保存明文密码.

我们还可以在 model 和 schema 上定义很多东西,如 statics 和 indexes. 详情请看官方文档

Create – 创建

我们将使用之前定义的 User 方法. mongoose Models 原生的 save 方法是专门用来向数据库存入真实数据的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var User = require('./app/models/user');

// 创建一个新的用户 newUser
var newUser = User({
name: 'Peter Quill',
username: 'starlord55',
password: 'password',
admin: true
});

// 保存 newUser
newUser.save(function(err) {
if (err) throw err;

console.log('User created!');
});

Read – 读取

我们多数情况下都是在查询数据,比如某个用户,或者全部用户,或者某类用户等等不同类别. 下面是几个例子:

FIND ALL

1
2
3
4
5
6
7
// 查询所有用户
User.find({}, function(err, users) {
if (err) throw err;

// object of the user
console.log(users);
});

FIND ONE

1
2
3
4
5
6
7
// 查询用户 starlord55
User.find({ username: 'starlord55' }, function(err, user) {
if (err) throw err;

// object of the user
console.log(user);
});

FIND BY ID

1
2
3
4
5
6
7
// 根据 ID 查询
User.findById(1, function(err, user) {
if (err) throw err;

// show the one user
console.log(user);
});

QUERYING

我们也可以直接使用 MongoDB 的原生语句进行查询

1
2
3
4
5
6
7
8
9
10
11
12
// 查询近一个月创建的用户数据

// 拿到距现在一个月前的时间点
var monthAgo = new Date();
monthAgo.setMonth(monthAgo.getMonth() - 1);

User.find({ admin: true }).where('created_at').gt(monthAgo).exec(function(err, users) {
if (err) throw err;

// show the admins in the past month
console.log(users);
});

Update – 更新

这里我们先查询某个特定的用户,然后更改一部分属性值,并再次存入更新后的数据.

查询,然后更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 查询到 ID 为 1 的用户
User.findById(1, function(err, user) {
if (err) throw err;

// 更改该用户的地址信息
user.location = 'uk';

// 保存用户信息
user.save(function(err) {
if (err) throw err;

console.log('User successfully updated!');
});

});

记得我们前面创建的 updated_at 函数吗,当保存更改的时候也会触发这个函数.

查询并更新

另一个更简便的方法是直接使用 mongodb 的 findAndModify 命令

1
2
3
4
5
6
7
8
// 找到用户 starlord55
// 更新数据为 starlord88
User.findOneAndUpdate({ username: 'starlord55' }, { username: 'starlord88' }, function(err, user) {
if (err) throw err;

// 更新后的用户会返回给我们
console.log(user);
});

根据 ID 查询并更新

1
2
3
4
5
6
7
8
// 查询用户 id 为 4
// 更新用户名为 starlord88
User.findByIdAndUpdate(4, { username: 'starlord88' }, function(err, user) {
if (err) throw err;

// 返回新的数据
console.log(user);
});

Delete – 删除

查询到用户,然后删除

1
2
3
4
5
6
7
8
9
10
11
// 查询到用户 starlord55
User.find({ username: 'starlord55' }, function(err, user) {
if (err) throw err;

// 删除
user.remove(function(err) {
if (err) throw err;

console.log('User successfully deleted!');
});
});

查询并删除 – 更方便的方法

1
2
3
4
5
6
7
// 查询 id 为 4 的用户
User.findOneAndRemove({ username: 'starlord55' }, function(err) {
if (err) throw err;

// 已经删除了
console.log('User deleted!');
});

根据 ID 查询并删除

1
2
3
4
5
6
7
// 查询 id 为 4 的用户
User.findByIdAndRemove(4, function(err) {
if (err) throw err;

// 已经删除了
console.log('User deleted!');
});

结论

希望这篇文章能成为您在使用 mongoose, Node.js 和 MongoDB 中的一篇好参考.

原文:Easily Develop Node.js and MongoDB Apps with Mongoose