上一篇博客我们介绍了Client与Back-End如何通信,成功打通了客户端到服务器端的。
现在我们来研究一下服务器内部的Back-End与Database之间的通信方式(初衷),以及nodejs服务端常用的2个操作和管理MongoDB的模块的对比(重点)。
下面关于mongoose和mongodb的对比中包含了Back-End与Database建立通信的方式,因此我们不单独拿出来讲。
简单说一下的话,就是数据库开一个默认监听端口出来,然后Back-End端调用接口去和默认监听端口建立连接。(通信内部协议我们不去深入。)
Ok,现在开始分析mongoose和mongdb模块。
一.初步分析mongoose和mongodb模块
关于mongoose的详情:
mongoose 是个 odm。odm 的概念对应 sql 中的 orm。也就是 ruby on rails 中的 activerecord 那一层。orm 全称是 Object-Relational Mapping,对象关系映射;而 odm 是 Object-Document Mapping,对象文档映射。
它的作用就是,在程序代码中,定义一下数据库中的数据格式,然后取数据时通过它们,可以把数据库中的 document 映射成程序中的一个对象,这个对象有 .save .update 等一系列方法,和 .title .author 等一系列属性。在调用这些方法时,odm 会根据你调用时所用的条件,自动转换成相应的 mongodb shell 语句帮你发送出去。自然地,在程序中链式调用一个个的方法要比手写数据库操作语句具有更大的灵活性和便利性。
用一段代码来说明mongoose的作用:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myproject');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
// we're connected!
var userSchema=new mongoose.Schema({
user:{ username:String,
password:String
},
contents:{
title:String,
poster:String,
post:String,
time:Date,
imgs:[],
comment:[]
}
});
var User = mongoose.model('user', userSchema);
var Frank = new User({
user:{ username:'Frank',
password:'12345678'
},
});
console.log(Frank.user);
Frank.save(function (err) {
console.log('保存成功');
});
});
我们将数据,也就是Frank的个人信息保存mongodb://localhost:27017/myproject的user model中。
这句话的直观意思是:我们将一个document,保存到myproject数据库的users collection中。
不知道聪明的你发现没有?
此处最巧妙的地方在于,model自动为我们创建了users这个collection。
所以可以理解model为document+collection的集大成者。
由此可见,mongoose是一个elegant mongodb object modeling for nodejs。
那么如何理解mongodb这个模块,它和mongoose有何异同?
看下下面这段代码:
var MongoClient = require('mongodb').MongoClient,
assert=require('assert');
var url = 'mongodb://localhost:27017/myproject';
MongoClient.connect(url,function(err,db){
assert.equal(null,err);
console.log("成功连接到服务器");
insertDocuments(db,function(){
db.close();
});
// db.close();
});
var insertDocuments = function(db,callback){
var collection = db.collection('documents');
collection.insertMany([
{a:1},
{a:2},
{a:3}
],function(err,result){
assert.equal(err,null);
assert.equal(3,result.result.n);
assert.equal(3,result.ops.length);
console.log("成功插入3个文档到集合!");
callback(result);
});
}
聪明的你一下就看出来了,mongodb模块中的命令更像是mongodb-shell中的命令。
所以这也是mongdb模块被称作MongoDB数据库的驱动的原因,说白了就是官方提供的一种管理和操作MongoDB数据库的nodejs接口。
mongodb是一个MongoDB官方为nodejs语言用户开发的本地驱动,除了mongodb这个nodejs驱动,MongoDB还提供了众多语言的驱动,包括Python,Php等等。
总结一下:
MongoDB:mongodb核心服务启动:mongod命令,开放27017端口允许建立连接.
mongodb package:管理数据库开关,collections和documents等,通过27017端口连接数据库。
mongoose package:数据库中集合的创建和管理,通过27017端口连接数据库。
PS:可以使用mongo命令开启MongoDB shell窗口,直接对话数据库
其实到这里还是对二者有些难以区分,请看这句话:
Let's face it, writing MongoDB validation, casting and business logic boilerplate is a drag. That's why we wrote Mongoose.
从这句话我们可以分析出来,如果只是使用mongodb的话,我们可能需要对数据进行验证,计算以及写复杂的业务逻辑,说白了就是处理collections里的documents比较麻烦,而moogose正好解决了这个问题。
二.进阶分析mongoose和mongodb模块
下面引用一段stackoverflow上的大神一段话:
I assume you already know that MongoDB is a NoSQL database system which stores data in the form of BSON documents. Your question, however is about the packages for Node.js.
In terms of Node.js, mongodb is the native driver for interacting with a mongodb instance and mongoose is an Object modeling tool for MongoDB.
Mongoose is built upon the MongoDB driver to provide programmers with a way to model their data.
EDIT: I do not want to comment on which is better, as this would make this answer opinionated. However I will list some advantages and disadvantages of using both approaches.
Using Mongoose, a user can define the schema for the documents in a particular collection. It provides a lot of convenience in the creation and management of data in MongoDB. On the downside, learning mongoose can take some time, and has some limitations in handling schemas that are quite complex.
However, if your collection schema is unpredictable, or you want a Mongo-shell like experience inside Node.js, then go ahead and use the MongoDB driver. It is the simplest to pick up. The downside here is that you will have to write larger amounts of code for validating the data, and the risk of errors is higher.
他给出了mongoose和mongodb的适用场景和优缺点。
关键处已做加粗标记,但是为了对比清晰些,这里我再列个表格。
Tables | 数据可预测性 | 优点 | 缺点 |
---|---|---|---|
mongoose | 可预测 | creation and management of data | handling schemas that are quite complex |
mongodb | 不可预测 | Mongo-shell like experience | write larger amounts of code for validating the data |
所以由此可以看出,我们应该结合具体的业务场景,在二者之间做一个合适的选择。
三.思考与总结
1.个人认为,数据类型一般来说都是可预测的。
举个简单的例子:用户的账号和密码,一般来说都是字符串类型。
此时使用mongoose就可以清晰得定义users的username和password为string类型;若不预先定义,那么需要去判断username和password是否符合存储要求。
2.这有些类似于关系型数据库中的数据类型定义,为什么要在Back-end定义数据类型呢?不能像关系型数据库一样,在数据库中定义表的字段时候声明数据类型吗?
答案是不行。
因为mongodb中的所有数据都是binary的,因此需要mongoose去做一个数据类型的定义,主要方法就是将document映射成一个对象。
3.二者都是通过MongoDB的27017默认监听端口进行连接,从而进行后续的集合和文档的定义,创建等操作。
道路是曲折的,但前途是光明的!
努力成为优秀的大前端工程师!
参考:
https://segmentfault.com/q/1010000010864304?_ea=2441566
https://stackoverflow.com/questions/28712248/difference-between-mongodb-and-mongoose?answertab=votes
https://gxnotes.com/article/168202.html
https://github.com/alsotang/node-lessons/tree/master/lesson15
期待和大家交流,共同进步,欢迎大家加入我创建的与前端开发密切相关的技术讨论小组:
- SegmentFault技术圈:ES新规范语法糖
- SegmentFault专栏:趁你还年轻,做个优秀的前端工程师
- 知乎专栏:趁你还年轻,做个优秀的前端工程师
- Github博客: 趁你还年轻233的个人博客
- 前端开发QQ群:660634678
微信公众号: 人兽鬼 / excellent_developers
努力成为优秀前端工程师!