1、MVC架构的实现
-
使用mongoose的原因:
用命令行来操作数据库的时候,手动操作非常麻烦,而且不利于未来的维护。因此我们还可以使用后端语言来操作数据库,也就是Node+express+mongoose。
-
将express改造成RMVC架构
- 改造理由:现在市场流行的是分布式,前后端分离,微服务。而单单使用express做出来的项目。routes文件夹既进行逻辑判断,又进行数据处理(数据库操作),又要暴露接口,没有达到功能的分离和封装。
- 选择MVC的原因:MVC是现在前端的主流框架(Model+View+Controller)
-
改造步骤:
项目流程:
思想:在文件夹中创建单独的model和controller文件夹,将routes的功能分离出去,路由仅仅是实现创建路由,其他的分给模块负责,最后引入即可。
具体实现:
1、路由模块创建接口。(实现增删改查为例)
const express = require( 'express' ) const router = express.Router() //将数据的操作传给了控制器 const positionController = require( '../controller/positonController' ) router .route('/position') .post(( req,res,next ) => { //为什么对象传参?对象是无序的,并且可以自由选择所要使用的参数。 positionController.add( { req,res,next,...req.body } ) }) .delete(( req,res,next ) => { positionController.del( { req,res,next,...req.query } ) }) .put(( req,res,next) => { positionController.update({req,res,next,...req.query}) }) .get( ( req,res,next ) => { positionController.query( { req,res,next,...req.query } ) } ) module.exports = router//(此处导出的模块,需要在app.js中导入使用)
2、positionController.js(控制器-实现逻辑)
//因为控制器是用来实现逻辑的,Model才是用来操作数据的,所以Controller将数据的操作给了Model实现。 const positionModel = require( '../model/positionModel' ) const positionController = { add ( { res,positionName,city,companyName }) { // 增 positionModel.add( { res,positionName,city,companyName }) }, del ({ res,positionName,city,companyName }) { // 删 positionModel.del( { res,positionName,city,companyName }) }, update ( data ) { // 改 positionModel.updated( data ) }, query ({ res,positionName,city,companyName }) { // 查 positionModel.query( { res,positionName,city,companyName }) } } module.exports = positionController
3、positionModel.js(模型-操作数据)
ps:Model可以连接数据库做数据操作,还可以暴露接口。
const db = require( '../db' ) const positionModel = { async add ( { res,positionName,city,companyName }) { const result = await db.position.add( { positionName,city,companyName }) if( result === 1 ){ //存储成功了 res.render('position.ejs',{ data: JSON.stringify({ ret: true, //这是认证方式 info: '添加成功', status: 1 }) }) }else{ //存储失败了 res.render('position.ejs',{ data: JSON.stringify({ ret: true, //这是认证方式 info: '添加失败了', status: 0 }) }) } res.json({ ret: true, status: '增加成功' }) }, async del ({ res,positionName,city,companyName }) { const result = await db.position.del( { positionName,city,companyName } ) switch ( result ) { case 0: res.render('position',{ data: JSON.stringify({ ret: true, info: '数据库没有这条数据', status: 0 }) }) break; case 1: res.render('position',{ data: JSON.stringify({ ret: true, info: '删除成功', status: 1 }) }) break; case 2: res.render('position',{ data: JSON.stringify({ ret: true, info: '重复删除', status: 2 }) }) break; default: break; } }, async updated ( { res,positionName,city,companyName} ) { const result = await db.position.update({positionName,city,companyName}) if( result === 0 ){ res.render('position',{ data: JSON.stringify({ ret: true, status: 0, info: '修改失败' }) }) }else{ res.render('position',{ data: JSON.stringify({ ret: true, status: 1, info: '修改成功' }) }) } }, async query ({ res,positionName,city,companyName }) { const result = await db.position.query({positionName,city,companyName }) res.render('position',{ data: JSON.stringify({ ret: true, info: '查询结果', data: result }) }) } } module.exports = positionModel
2、mongoose
数据库操作流程:
-
1、安装mongoose
-
2、连接数据库
-
3、存储数据的步骤:定义Schema (骨架) > 创建model(模型)> Entity实例化方法。
- 创建骨架(Schema)
它可以理解为数据库模型骨架,可以看作工厂中模具一样,好比一个茶杯,喝水是茶杯最终的功能,茶杯本身就像是Model,那么茶杯的批量生产是需要靠工厂的模具成型的。Schema不仅定义了文档结构和使用性能,还可以有扩展插件、实例方法、静态方法、复合索引、文档生命周期钩子。
Schema概念:一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力。
- 创建模型
Model概念:由Schema发布生成的模型,具有抽象属性和行为的数据库操作对。
- 实例化
Entity概念:由Model创建的实体,他的操作也会影响数据库 。
项目流程:
1、在项目中一般需要创建一个db文件夹,来单独管控对于数据库的操作,便于实现功能的分离。
2、创建一个index.js作为数据库总体的管控,主要用来将封装的各个模块引入进来。
// 1. 连接数据库
const connect = require( './connect' )
connect.run()
// 2. 创建骨架
const { positionSchema } = require( './schema/index.js' )
// 3. 创建模型
const { dbPositionModel } = require( './model/index.js' )
const position_model = dbPositionModel( {
collectionName: 'positions',//集合名称一定要是复数
schemaName: positionSchema
})
const db = {
position: {
add ( data ) {
// 做数据库操作 , 添加一条数据进入数据库
// 4. 创建实体 【 实例化模型得到实体 】
// Promise +async-await可以实现得到内层数据。
return new Promise(( resolve,reject ) => {
const position = new position_model( data )
// 将数据保存在了数据库
position.save( error => {
if( error ) {
// 存储失败
resolve( 0 )
}else{
// 表示存储成功
resolve( 1 )
console.log( '存储成功' )
}
})
})
},
del ( data ) {
return new Promise(( resolve,reject ) => {
position_model.find( data, ( error,docs ) => {
if( !(docs.length === 0) ) {
//找到匹配的数据了 , 开始删除
position_model.findById( docs[0]._id, ( error,result ) => {
if( result ){
//可以删除
resolve( 1 )
result.remove()
}else{
// 没必要删除了
resolve( 2 )
}
})
}else{
// 没有找到匹配的条件,不用删除
resolve( 0 )
}
})
})
},
update ( data ) {
return new Promise(( resolve,reject ) => {
position_model.find( data, ( error, docs ) => {
if( !( docs.length === 0 ) ){
//证明找到那条数据了
position_model.findById( docs[0]._id, ( error,result ) => {
result.city = '北京'
result.save( error => {
if( error ) {
resolve( 0 )
}else{
resolve( 1 )
}
})
})
}else{
// 没有找到
}
})
})
},
query ( data ) {
return new Promise(( resolve,reject ) => {
if( data ){
// 精确查找某一条
position_model.find( data, ( error,docs ) => {
resolve( docs )
})
}else{
// 查所有的
position_model.find({},( error,docs ) => {
resolve( docs )
})
}
})
}
}
}
module.exports = db //此处导出的模块在Model中得以引用。
3、封装连接数据库的功能模块,新建connect.js
const mongoose = require('mongoose');
const dbName = 数据库的名称;
const connect = {
run() {
mongoose.connect(`mongodb://127.0.0.1:27017/${dbName}`, (error) => {
if (error) console.log(error);
console.log('数据库连接成功')
})
}
}
module.exports = connect;
4、创建骨架(骨架和模型可以有很多个,所以此部分一般需要单独创建文件夹进行管控,结构清晰)
在db文件夹中创建schema文件夹,文件夹中创建一个index.js作为总的管控骨架的文件(类似于表),这样数据库引入创建骨架模块时候只需要引入一个模块即可,其他的是相关骨架的封装(行和列)。
index.js
const positionSchema = require('./positioSchema');
module.exports = {
positionSchema
}
positionSchema.js
const mongoose = require('mongoose');
const positionSchema = new mongoose.Schema({
positionName: String,
city: String,
companyName: String
})
module.exports = positionSchema;
5、创建模型。
在db文件夹中创建一个model文件夹,文件夹中创建一个index.js作为总的管控模型的文件(类似于表),其他的是相关模型的封装(行和列)
index.js
const dbPositionModel = require('./dbPositionModel');
module.exports = { dbPositionModel };
dbPositionModel.js
const mongoose = require('mongoose');
const dbPositionModel = ({ collectionName, schemaName }) => {
//这里参数中集合的名称一定要主要加复数,否则数据库会默认添加s。
return mongoose.model(collectionName, schemaName);
}
module.exports = dbPositionModel;