原文链接:http://blog.csdn.net/sodino/article/details/51590263(mongodb教程)
理解Schema
传统的MySQL、Oracle等关系型数据库中,在存储数据之前,开发者必须道德为数据定义数据表,并且为该数据表定义一些字段,从而使数据模型得到实现。
可以说,在关系型数据库中,一个数据表就是一个数据架构。它预先定义了开发者可以使用的数据模型。
但MongoDB是面向文档的数据库,不是关系型数据库。被认为是无数据架构的。
然而数据架构仍然是有用的,可以使人以易读的方式来描述数据库中的数据内容,并为这些数据定义一些规则。
如Mongoose可以对Number
的数据设置最小值min
与最大值max
;可以对Date
设置默认值为当前时间;可以对String
设置存储为小写模式并去除头尾空白字符。
而以上所说的功能都在Mongoose的设计理念中,都由Schema
的定义来实现。
Schema的定义
在Sodino的MongoDemo工程中,需要对手机进行数据架构的定义。具体实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var mongoose =
require(
'mongoose');
var Schema = mongoose.Schema;
var phoneSchema =
new Schema({
device :
String,
isSmart :
Boolean,
releaseTime :
Date,
price :
Number,
apps : [{name :
String}],
manufacturer: {
name :
String,
country :
String
}
});
|
至此,对手机的Schema
定义完成。
当然,也可能通过Api对Schema进行动态扩展,如需要增加手机的颜色这一数据属性,则可以用如下代码实现:
1
|
phoneSchma
.add(
{color : 'string'})
|
Schema
中所支持的数据类型有:
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- Objectid
- Array
创建Model
下一步在代码中使用Schema
所定义的数据模型,需要将定义好的phoneSchema
转换为Model
。
可以使用mongoose.model(modelName, schema)
进行转换。
1
|
var Phone = mongoose.model(
'Phone', phoneSchema);
|
有Schema
后为什么还要有Model
呢?
在Mongoose的设计理念中,Schema
用来也只用来定义数据结构,具体对数据的增删改查操作都由Model
来执行。
就好比富士康用模具组装出一台手机后,当需要打电话时是用手机来打而不是用模具。
创建数据实例
Model
相当于数据的构造函数。当需要实例化出一个数据对象实例时,可以使用new
操作符来实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var iPhoneSE = new Phone(
{
device :
"iPhone SE",
isSmart :
"true",
releaseTime :
"2016-03-21 10:00:00",
price :
4999,
apps : [{
name :
"Safari"}, {
name :
"Map"}, {
name :
"Tinder"}],
manufacturer: {
name :
"Apple",
country
" : "The United States
"
}
}
);
|
在上面的代码中,数据的具体值以JSON对象的形式作为参数传入Phone
即构造出数据对象实例iPhoneSE
。
在sodino#MongoDemo示例代码中,Sodino使用了require(json.file.path)
来获取JSON对象再传参到Phone
的方式。简化了JavaScript的代码量。
1
2
3
4
|
var raw;
raw =
require(
'./raw.iPhoneSE.json');
var iPhoneSE =
new Phone(raw);
|
1
2
3
4
5
6
7
8
9
10
11
12
|
{
"device" :
"iPhone SE",
"isSmart" :
"true",
"releaseTime" :
"2016-03-21 10:00:00",
"price" :
4999,
"apps" : [{
"name" :
"Safari"}, {
"name" :
"Map"}, {
"name" :
"Tinder"}],
"manufacturer": {
"name" :
"Apple",
"country" :
"The United States"
}
}
|
Model实例方法
可以为Model
的实例添加自定义方法,作法也很简单,只要将自定义的方法添加到Schema.methods
即可。
可以设想这样的功能,Phone
的内容很多,但客户最关心哪个手机价格是多少,那么可以添加一个实例方法printBrief()
用来打印出这两个信息就好了。
如下代码所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var mongoose =
require(
'mongoose');
var Schema = mongoose.Schema;
var phoneSchema = new Schema({
...
...
...
...
});
var Phone = mongoose.model(
'Phone', phoneSchema);
// 这里,为Model添加实例方法。
phoneSchema.methods.printBrief =
function () {
console.log(this.device,
'¥'+this.price);
};
|
printBrief()
的使用方法如下:
1
2
3
|
var iPhoneSE =
new Phone(raw);
iPhoneSE.printBrief();
|
控制台输出为:
需要注意的是,Model实例方法只能被Model的实例调用,不能被Model直接调用,否则会抛出is not a function
异常。这相当于Java的非静态方法不能被Class直接调用。异常如下所示:
1
2
3
4
5
6
|
TypeError: Phone.printBrief is not a function
at Query.<anonymous> (D:
\desk
\JavaScript
\MongoDemo
\app.js:427:14)
at D:
\desk
\JavaScript
\MongoDemo
\node_modules
\kareem
\index.js:177:19
at D:
\desk
\JavaScript
\MongoDemo
\node_modules
\kareem
\index.js:109:16
at _combinedTickCallback (node.js:370:9)
at process._tickCallback (node.js:401:11)
|
Model静态方法
与实例方法相对应的是静态方法。只要在Schema.statics
中添加新声明的方法即可。
可以设想这样的功能,想查询一下Phone
到底存储了多少个手机型号,可以定义一个静态方法printCount()
,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var mongoose =
require(
'mongoose');
var Schema = mongoose.Schema;
var phoneSchema = new Schema({
...
...
...
...
});
var Phone = mongoose.model(
'Phone', phoneSchema);
// 这里,为Model添加静态方法。
phoneSchema.statics.printCount =
function () {
console.log(this.device,
'¥'+this.price);
this.count({}, (err, count) => {
console.log(
'---printCount()-----------------------------')
if (err) {
console.log(err);
}
else {
console.log(
'phone count=' + count);
}
});
};
|
调用方法如下:
控制台打印如下:
1
2
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
说了这么多,接下来的文章开始介绍数据库的增删改查了哈…
下一篇:mongoose教程—存储
相关链接
Mongoose Quick Start v4.4.19
Mongoose Schemas v4.4.19
About Sodino