一、Mongoose简介
Mongoose是一个让我们可以通过Node来操作MongoDB的模块,是一个对象文档模型(ODM),它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。大多数情况下,Mongoose被用来把结构化的模式应用到一个MongoDB集合,并提供验证和类型转换等。简单的说它是前端开发用来操作MongoDB的一个工具,类似于后台开发使用Mybatis等操作Mysql。
Mongoose的优点:
1️⃣可以为文档创建一个模式结构(Schema),用来约束MongoDB中的文档对象
2️⃣可以对模型中的文档对象进行验证
3️⃣数据可以通过类型转换转换为对象模型
4️⃣可以使用中间件来与应用的业务逻辑挂钩
Mongoose为我们提供了几个对象:
①Schema(模式对象):约束数据库中的文档对象的结构
②Model:作为集合中所有文档对象的表示,相当于MongoDB数据库中的collection
③Document:表示集合中的具体文档,相当于集合中的一个具体文档
其他语言与MongoDB的对接请参考:菜鸟教程
二、Mongoose的使用
使用Mongoose时,必须先先有schema,再通过schema创建model,最后通过model创建document。
1、环境搭建
①在工程中引入Mongoose依赖
npm i mongoose --save
②在项目中引入mongoose
var mongoose = require("mongoose");
③使用mongoose连接MongoDB数据库:mongoose_test是数据库名,不需要事先创建,若端口号是默认的27017,则可以不写
mongoose.connect("mongodb://127.0.0.1/mongoose_test" , { useMongoClient: true});
④监听数据库的连接状态
mongoose.connection.once("open",function(){
console.log("数据库连接成功~~~");
});
mongoose.connection.once("close",function(){
console.log("数据库连接已经断开~~~");
});
⑤断开连接:一般不需要调用
//断开数据库连接
mongoose.disconnect();
2、使用操作mongoose进行MongoDB的增删改查等操作
①使用mongoose.Schema创建schema对象
//将mongoose.Schema赋值给一个新变量,也可以直接只用mongoose.Schema
var Schema = mongoose.Schema;
//创建Schema对象:schema对象是对由其创建的Model(可看做是collection)中的所有文档对象的约束
var stuSchema = new Schema({
name:String,
age:Number,
gender:{
type:String,
default:"female"
},
address:String
});
②通过Schema来创建Model:Model代表的是数据库中的集合,通过Model才能对数据库进行操作,这些操作的详情请参考官方文档
//mongoose会自动将集合名变成复数
var StuModel = mongoose.model("student" , stuSchema);
//向数据库中插入一个文档
StuModel.create({
name:"白骨精",
age:16,
address:"白骨洞"
},function (err) {
if(!err){
console.log("插入成功~~~");
}
});
StuModel.find({name:"唐僧"},function (err , docs) {
if(!err){
console.log(docs);
}
});
StuModel.find({},{name:1 , _id:0},function (err , docs) {
if(!err){
console.log(docs);
}
});
StuModel.find({},"name age -_id", {skip:3 , limit:1} , function (err , docs) {
if(!err){
console.log(docs);
}
});
StuModel.findOne({} , function (err , doc) {
if(!err){
console.log(doc);
}
});
StuModel.findById("59c4c3cf4e5483191467d392" , function (err , doc) {
if(!err){
//通过find()查询的结果,返回的对象,就是Document,文档对象
//Document对象是Model的实例
console.log(doc instanceof StuModel);
}
});
StuModel.updateOne({name:"唐僧"},{$set:{age:20}},function (err) {
if(!err){
console.log("修改成功");
}
});
StuModel.remove({name:"白骨精"},function (err) {
if(!err){
console.log("删除成功~~");
}
});
StuModel.count({},function (err , count) {
if(!err){
console.log(count);
}
});
三、事务问题
MongoDB作为数据库必然存在事务问题,那么事务有没有可能通过前端解决呢?答案是不可能。原因很简单,前端其实就是用户的个人电脑,各个用户之间的电脑可能是相互不通信的,那么就不可能仅通过前端解决事务的问题。举例来说:用户A从MongoDB中查询出_id是123456的文档对象,想修改该对象的一个属性值,此时用户B也查询出_id为123456的该对象,但在A完成修改之前B将其删除了,那么A的操作必然是失败的,其他诸类操作也会面临这个问题。既然前端不可能完成事务控制,那能不能将事务控制交给MongoDB呢?比如说一旦有用户查询_id为123456的对象,就将该对象加锁,直到该用户操作完该对象,其他用户才允许查询和修改该对象,理论上这是可以的。其实这和MySQL等是一个逻辑,这其中也必然需要通过事务隔离级别等对数据的读写性能进行取舍。
那么一个可怕的问题来了:对于web应用来说(app可能会导致安装过于庞大,手机会扛不住),前端直接对接数据库,相当于将所有的运算都放在了用户自己的电脑上,以现在电脑的配置是不成问题的,更何况此时每个用户的电脑只需要处理用户自己的数据,计算的压力其实是很小的,当然这对浏览器的要求要更高;还有一点这样一来企业的成本也会大大降低(需要的服务器数量大大减少了,只需要两台服务器:一台前端服务器,一台数据库服务器,数据库服务器可酌情增加,有高并发时再还一些中间件的加持),这不是比后台分布式更有优势吗?后台分布式部署的目的不就是为了转移计算机的计算压力吗?还有什么方式能比将计算压力转移给用户自己更加符合分布式的需求呢?而后台分布式再怎么分开部署一台服务器也需要处理成千上万个用户的数据,这么一想后台岂不是没有了存在的必要?