深入浅出mongodb之实战
人的一生就像一篇文章,只有经过多次精心修改,才能不断完善。
前言
再好的东西不使用它,他终究不属于你,只有我们真正的把它运用到实际,真正的理解它,才能发挥它的最大作用正所谓实践出真理
。深入浅出mongodb(一)和深入浅出mongodb(二)两篇文章讲述了一些安装和使用的基础知识,这篇文章小编将带你走进实战世界,真正体会项目中是怎么使用mongodb开发,让我们一起揭开它神秘的面纱。
准备工作
项目中我们用到的是基于node
的express[1] 框架
npm i express-generator -g
express-generator
是一个express的应用生成器,可以快速的创建一个express应用。
安装完成上述指令之后,我们可以检查一下安装的express是否能用
express --version
接着我们就可以创建项目了,在创建项目的时候可以先express -h
来查看一下,express命令的参数
$ express -h
Usage: express [options] [dir]
Options:
--version output the version number
-e, --ejs add ejs engine support
--pug add pug engine support
--hbs add handlebars engine support
-H, --hogan add hogan.js engine support
-v, --view <engine> add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
--no-view use static html instead of view engine
-c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
--git add .gitignore
-f, --force force on non-empty directory
-h, --help output usage information
在默认的情况下,我们创建的项目模板引擎使用的是jade,个人感觉ejs[2]模板引擎比较好用,所以我们可以通过修改模板引擎的方式创建项目
express backend -e
创建好项目之后,我们express骨架已经搭建好了,我们可以启动项目看一下效果
cd backend
npm i
npm start
如果出现下面的结果说明我们的启动成功了
$ npm start
> backend@0.0.0 start C:UsersDELLDesktopbackend
> node ./bin/www
这个时候我们打开项目先熟悉一下项目目录
-
bin
是启动目录,里面有一个www启动文件,默认的端口是3000,如果不合适我们可以手动修改 -
node_modules
这个目录下面是我们安装的所有依赖 -
pubilc
这个文件夹下是我们前端存放静态资源的 -
routes
这个文件是存放路由的,主要编写前端发送请求和响应数据给前端 -
views
这个文件夹中ejs文件结尾的文件是后端的模板文件 -
app.js
是入口文件,模板配置和总路由文件 -
package.json
这个是包的描述文件,我们主要关注的是scripts
和dependencies
。
我们在执行node文件的时候,如果修改了node文件,每次执行都需要重新启动项目才行,为了方便我们可以使用
nodemon
来监听项目的改动,不再需要重复启动项目,这么方便的东西用起来能不香吗??
npm i nodemon -g
//package.json
"scripts": {
"start": "nodemon ./bin/www"
},
完成上述的操作之后,我们启动项目npm start
数据库
安装
npm i mongoose -S
完成安装之后我们需要在app.js
里引入并且配置数据库
//app.js
//引入数据库
const mongoose = require('mongoose');
//连接数据库
mongoose.connect(`mongodb://localhost:27017/test`,{
useNewUrlParser: true,
useUnifiedTopology: true
});
设置跨域
在开发中,我们采用的都是前后端分离
的状态,在本地的开发环境中我们无法避免的会遇到跨域[3]的情况,我们这里设置允许所有的源访问
app.use("/*", function (req, res, next) {
//设置headers
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTION");
//自定义请求头
res.header(
"Access-Control-Allow-Headers",
"Content-type,Accept,X-Access-Token,X-Key"
);
if (req.method == "OPTIONS") {
res.status(200).end();
} else {
next();
}
});
OPTIONS
这个是预检请求,如果遇到了不同源请求时,会先询问来自哪个源对源进行检查之后,做出响应。
实际上在真正的开发环境中,如果我们这么设置允许所有的的源都可以访问会有很多问题,我们可以使用cors[4]来代替它
当然如果在生产中我们采用nginx部署之后,就不存在跨域了?
接下来就是我们平时常说的
mvc
模式下的m
和c
部分了,为了结构清晰,便于维护我们分成四部分scheme
,model
,controller
,api
scheme
在项目的根目录下创建scheme文件夹,因为这里项目简单我们就创建一个index.js
文件,当然如果项目模块和功能比较多的话,我们可以按照功能来创建文件,因人而异。
const mongoose = require("mongoose");
const Scheme = mongoose.Schema;
const ObjectId = mongoose.Types.ObjectId;
//物品表
const gooseScheme = Scheme({
id: ObjectId,
name: String,
age: Number,
image: String,
price: Number,
description: String,
user: {
type: ObjectId,
ref: "User",
},
});
//用户表
const userScheme= Scheme({
id: ObjectId,
name: String,
});
module.exports = { gooseScheme, userScheme };
model
在项目的根目录下创建model的文件夹,创建index.js
文件:
const mongoose = require("mongoose");
const model = mongoose.model.bind(mongoose);
const scheme = require("../scheme");
const { gooseScheme, userScheme } = scheme;
const GooseModel = model("Goose", gooseScheme);
const UserModel = model("User", userScheme);
module.exports = { GooseModel, UserModel };
controller
在项目的根目录下创建controller
的文件夹,根据功能我们创建userController.js
和gooseController.js
//userController.js
const Model = require("../model");
const { UserModel } = Model;
const userController = {
all(req, res) {
UserModel.find({}).then(docs => res.json(docs));
},
create(req, res) {
const requestBody = req.body;
const newUserModel = new UserModel(requestBody);
newUserModel.save((err, save) => {
UserModel.findOne({ _id: save._id }).then((docs) => res.json(docs));
});
},
byId(req, res) {
const idParams = req.params.id;
UserModel.findOne({ _id: idParams }).then((docs) => res.json(docs));
},
update(req, res) {
const idParams = req.params.id;
let requestBody = req.body;
UserModel.updateOne({ _id: idParams }, { ...requestBody }, (err, docs) => {
res.json(docs);
});
},
remove(req, res) {
const idParams = req.params.id;
UserModel.findOne({ _id: idParams }).remove((err, docs) =>
res.json(idParams)
);
},
};
module.exports = userController;
//gooseController.js
const Model = require("../model");
const { GooseModel } = Model;
const gooseController = {
all(req, res) {
GooseModel
.find({})
.populate("user")
.then(docs=> res.json(docs));
},
byId(req, res) {
const idParams = req.params.id;
GooseModel
.findOne({ _id: idParams })
.populate("user")
.then((docs) => res.json(docs));
},
create(req, res) {
const requestBody = req.body;
const newGooseModel = new GooseModel(requestBody);
newGooseModel.save((err, saved) => {
console.log(saved);
GooseModel
.findOne({ _id: newGooseModel._id })
.populate("user")
.then((docs) => res.json(docs));
});
},
update(req, res) {
const idParams = req.params.id;
const requestBody = req.body;
GooseModel.updateOne({ _id: idParams }, { ...requestBody }, (err, docs) => {
res.json(docs);
});
},
remove(req, res) {
const idParams = req.params.id;
gooseModel
.findOne({ _id: idParams })
.remove((err, docs) => res.json(idParams));
},
};
module.exports = gooseController;
api
在express中有这么一句话一切皆为中间件
,我们在设置路由的时候,需要在app.js
中注册之后才能使用
//app.js
var api = require("./routes/api");
app.use("/api",api)
配置routes
文件夹下的api.js
文件
const express = require("express");
const router = express.Router();
const gooseController = require("../controller/gooseController");
const userContoller = require("../controller/userController");
router.get('/user',userContoller.all);
router.get('/user/:id',userContoller.byId);
router.post('/user', userContoller.create);
router.put('/user/:id', userContoller.update);
router.delete('/user/:id', userContoller.remove);
router.get('/goose', gooseController.all);
router.get('/goose/:id', gooseController.byId);
router.post('/goose', gooseController.create);
router.put('/goose/:id', gooseController.update);
router.delete('/goose/:id', gooseController.remove);
module.exports = router
成果
我们完成上面的步骤之后,我们需要自测试一下接口和逻辑是否正确
查询人员
localhost:3000/api/user
get
新增人员
localhost:3000/api/user
post
删除人员
localhost:3000/api/user/:id
delete
新增物品
localhost:3000/api/goose
post
查询物品及所属人员
localhost:3000/api/goose
get
最后
本文结束,有什么问题和有错误的地方,欢迎大家的留言和评论,还有后续更新,下期更加精彩 ???
参考资料
[1]
express: https://www.expressjs.com.cn/
[2]
ejs: https://ejs.bootcss.com/
[3]
跨域: http://www.ruanyifeng.com/blog/2016/04/cors.html
[4]
cors: https://www.npmjs.com/package/cors
- 【Python环境】Python分类现实世界的数据
- Android基础总结(7)——异步消息处理
- No.008 String to Integer (atoi)
- No.007 Reverse Integer
- No.006 ZigZag Conversion
- No.005 Longest Palindromic Substring
- Android基础总结(6)——内容提供器
- No.004 Median of Two Sorted Arrays
- No.001 Two Sum
- No.002 Add Two Numbers
- 【Python环境】探索 Python、机器学习和 NLTK 库
- 【机器学习】机器学习之组合算法总结
- IE 11浏览器0day漏洞(CVE-2015-2425)UAF分析
- 【Python环境】Python可视化工具综述
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Chrome代码调试指南
- Maven安装与配置
- CentOS7安装elk,并监控Nginx的access.log日志
- Aria2 + Rclone 实现离线下载 | 完美脚本配置 | 解决无法上传问题
- alpine使用的避坑指南
- elasticSearch学习(八)
- Python自学成才之路 魔术方法之比较运算符,赋值运算符
- Go语言(golang)新发布的1.13中的Error Wrapping深度分析
- 使用k8s容器钩子触发事件
- Python自学成才之路 魔术方法之属性访问控制
- Python自学成才之路 彻底搞懂python变量作用域
- Python自学成才之路 什么是元类
- 调试 Go 的代码生成
- Kubernetes中的Volume介绍
- Python自学成才之路 终于弄清楚类方法,静态方法的区别了