文章目录
  1. 1. 前言
  2. 2. 安装
  3. 3. 创建连接
  4. 4. Schema、Model和Entity
    1. 4.1. 关于Schema.Types
  5. 5. Schema的扩展
    1. 5.1. 实例方法
    2. 5.2. 静态方法
    3. 5.3. 虚拟属性
  6. 6. 待续

最近一直在忙着手上的项目和工作交接(辞职了),一直没时间更新博客,还好已经交接完毕

前言

Mongoose 是 Mongodb的一个对象模型工具(简称为ORM),可以工作于异步环境下。使用Mongoose很长一段时间了,几乎是跟nodejs一起配套学习的,也在项目中写了不少的这方面的代码,很可惜的是一直没去总结,现在就好好总结一下吧。

安装

1
$ npm install mongoose

创建连接

Mongoose 连接数据库有两种方式,

1
2
3
4
5
6
7
var mongoose = require('mongoose');

//第一种方式
mongoose.connect('mongodb://localhost/testDB'); //个人喜欢用这种方式

//第二种方式
mongoose.createConnection('localhost','testDB');

以上两种方式有所不同,简单的说就是,如果你的程序只使用一个数据库,就应该使用mongoose.connect()这种方式,如果你需要创建额外的连接,例如连接多个mongoDB,就应该使用mongoose.createConnection()这种方式。

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
26
27
28
29
30
31
32
33
34
35
//摘自以前写的一个项目,文件名为db.js
var mongoose = require('mongoose');

var dbConfig = {};
//生产环境
if(process.env['production']) {
dbConfig = {
hostname: "localhost",
database: "dbTest",
username:"root",
password:process.env["dbPwd"],
};
mongoose.connect('mongodb://'+dbConfig.username+":"+dbConfig.password+'@'+dbConfig.hostname+'/'+dbConfig.database);
} else {
// 开发环境
dbConfig = {
hostname: "localhost",
database: "dbTest"
};
mongoose.connect('mongodb://'+dbConfig.hostname+'/'+dbConfig.database);
}

console.info('Database connecting......');

db = mongoose.connection;
db.on('error', function(err) {
console.info('Connect to Database failed');
console.error(err);
});

db.on('open', function() {
console.info('Connected to mongo database on '+new Date());
});

module.exports = mongoose;

Schema、Model和Entity

  • Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力。
  • Model : 由Schema发布生成的模型,具有抽象属性和行为的数据库操作对。
  • Entity : 由Model创建的实体,他的操作也会影响数据库

其三者的关系可以简述为:Schema生成Model,Model创造Entity,Model和Entity都可对数据库操作造成影响,但Model比Entity更具操作性。

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
26
27
28
//示例代码
var mongoose = require('./db')

//这是schema,定义一个Schema
var itemSchema = new mongoose.Schema({
name: String,
price: {
type: Number,
'default': 100 //默认值,由于default是一个js语言里面的一个关键字,用''加以区分,习惯问题
},
discount: {
type: Number,
'default': 100 //由于js的双精度浮点不精确,因此应尽量避免用小数
}
});

//这是model,将Schema发布为Model
var itemModel = mongoose.model('item', itemSchema);

//这是entity,用Model创建Entity
/*
var item = new itemModel({
name: 'testname',
price: 99,
discount: 50
});
item.save();
*/

关于Schema.Types

Schema.Types是由Mongoose内定的一些数据类型,基本数据类型都在其中,他也内置了一些Mongoose特有的Schema.Type。当然,你也可以自定义Schema.Type,只有满足Schema.Type的类型才能定义在Schema内。

1
2
3
4
//打印出所有types
console.log(mongoose.Schema.Types);

//ps:mongodb的主键_id 的type是ObjectId

这里有四个个人感觉比较特殊的type,分别是

  • ObjectId //mongodb中的主键
  • Buffer //Buffer和ArrayBuffer是Nodejs两种隐藏的对象,相关内容请查看NodeJS-API,项目中没试用过,无法具体说出
  • Mixed //混合类型
  • Array //Array在JavaScript编程语言中并不是数组,而是集合
    /*
        var ExampleSchema1 = new Schema({array:[]});
        var ExampleSchema2 = new Schema({array:Array});
        var ExampleSchema3 = new Schema({array:[Schema.Types.Mixed]});
        var ExampleSchema4 = new Schema({array:[{}]});
    */
    

Schema的扩展

实例方法

有的时候,我们创造的Schema不仅要为后面的Model和Entity提供公共的属性,还要提供公共的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//查询相同价格的商品
itemSchema.methods.getSimilarPrice = function(callback) {
return this.model('item').find({
price: this.price
},callback);
}
//获取商品的真正价格
itemSchema.methods.getRealPrice = function() {
return this.price * this.discount / 100;
}


var item = new itemModel({
name: 'testname',
price: 99,
discount: 50
});
//打折后价格
console.log(item.getRealPrice());
//相同价格的商品
item.getSimilarPrice(function(err, items) {
//console.log(items);
});

静态方法

静态方法在Model层就能使用

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
26
27
28
29
30
31
//静态文件定义
itemSchema.statics.findByName = function(name,callback) {
this.find({
name: name
},callback);
}

//使用
var itemModel = mongoose.model('item', itemSchema);
itemModel.findByName('test', function(err, items) {
//console.log(items);
});

ps:这里有另外一种方式能让model层去调用自定义方法,使用prototype,如下:

//定义model
var itemModel = mongoose.model('item', itemSchema);

//model里的原型方法
itemModel.prototype.findByName = function(name,callback) {
this.find({
name: name
},callback);
}

//使用
itemModel.findByName('test', function(err, items) {
//console.log(items);
});

//不知道有什么不一样的地方,求大神赐教。

虚拟属性

Schema中如果定义了虚拟属性,那么该属性将不写入数据库,例如:

1
2
3
4
5
6
7
8
9
10
itemSchema.virtual('realPrice').get(function() {
return this.price * this.discount / 100;
});
//使用
var item = new itemModel({
name: 'testname',
price: 99,
discount: 50
});
console.log(item.realPrice);

如果知道realPrice,想得出折扣也是可以的,如下:

1
2
3
itemSchema.virtual('realPrice').set(function(rPrice) {
this.discount = rPrice/this.price*100;
});

待续

文章目录
  1. 1. 前言
  2. 2. 安装
  3. 3. 创建连接
  4. 4. Schema、Model和Entity
    1. 4.1. 关于Schema.Types
  5. 5. Schema的扩展
    1. 5.1. 实例方法
    2. 5.2. 静态方法
    3. 5.3. 虚拟属性
  6. 6. 待续