connect连接数据库文件
// 使用mongoose模块
// 创建schema对象和创建连接都需要引用到mongoose模块
// 第一步
var mongoose = require('mongoose');
// 连接数据库
mongoose.connect(`mongodb://localhost/mjn`, {
useNewUrlParser: true,
useUnifiedTopology: true
});
// mongoose.connect第一个参数当中的mongodb表示连接本地数据库
// localhost表示数据库本地的一个域名
// localhost后面的:27017表示端口号默认端口号为27107,如果不写端口号则使用默认端口号
// 后面的mjn是数据库的名字
// 第二步
// var db = mongoose.connection;表示数据库的连接对象
var db = mongoose.connection;
// on表示监听事件,如果数据库连接错误就会触发打印数据库连接失败
db.on('error', function () {
console.log("数据库连接失败!")
});
db.once('open', function () {
console.log("数据库第一次连接成功!");
});
附带图片
userModel.js
// 创建schema对象和创建连接都需要引用到mongoose模块
var mongoose = require("mongoose")
// 第三步
// 创建schema对象 相当于创建数据库表的表头
var foodSchema = new mongoose.Schema({
// 注意下列易犯错点
// 如下我们要插入对数据操作时要写清除有表头,并且给清除表头的字符数据类型不然就会报错
//例如你下面代码插入数据库内容的时候写了{name:"苹果",age:60,sex:"未知",boy:"男"}
// 但是你在创建schema对象,创建数据库表头的时候没有定义boy属性并且定义清楚他的数据类型就会报错
// 并且boy:"男"这条数据也无法写入数据库的表当中
// require:true表示为必填项
// name菜名
name: {
type: String,
required: true
},
// price价格
price: {
type: String,
required: true
},
// desc描述
desc: {
type: String,
required: true
},
// img图片
img:{
type: String,
required: false
},
// foodType食品类别
foodType:{
type: String,
required: true
},
_id:{
type: mongoose.Schema.Types.ObjectId,
required: false
},
});
// 第四步
// 将schema对象和数据集合进行关联
// 如果参数一这个集合是 你未创建的那么系统会默认帮你创建,并且如果参数一写的是单数形式英文单词,默认会给你变成复数
// mongoose.model("参数一填你要关联的集合名","参数二填上面创建的schema对象如上的foodSchema")
// 数据库相关的命名或者参数都不能写中文,比如数据库名,集合名不可以创建为中文
var foodModel = mongoose.model('foods', foodSchema);
// 因为我们后面对数据库的增删改查都需要用到数据模型foodModel所以我们需要将他暴露出去
module.exports = foodModel
图片资源
mongoose增删改查封装.js
// 1.添加菜品
var userModel = require("./userModel")
const foodModel = require("./userModel")
const router = require("../router/loginAndReg")
// 一:添加食品
var insertFood = async (obj, res) => {
try {
var result = await userModel.insertMany(obj)
res.send(`{err:1,msg:"菜品添加成功,祝您用餐愉快!","添加的菜式":${result}}`)
} catch (e) {
res.send(`{err:-1,msg:"菜品添加失败,请重新添加!","添加失败的原因":${e}}`)
}
}
// 二:查询全部菜品/或者模糊查找
var findFood = async function (obj, res) {
if (arguments.length == 1) {
try {
var result = await userModel.find()
res.send(`${result}`)
} catch (e) {
res.send(`{err:-1,msg:"菜品查询失败,请重新失败!","查询失败的原因":${e}}`)
}
} else {
try {
var result = await userModel.find(obj)
if (!result[0]) {
res.send(`您输入的菜,我们厨子还不会做哟`)
} else {
res.send(`${result}`)
}
} catch (e) {
res.send(`{err:-1,msg:"菜品查询失败,请重新失败!","查询失败的原因":${e}}`)
}
}
}
// 三:删除菜品
var delFood = async function (_id) {
// Object.prototype.toString.call()
var result= await userModel.deleteOne({_id},function(err){console.log(err);})
return result
}
// 四:修改菜品
var xiuGai=async function(_id,data){
var result= await userModel.updateOne({_id},data)
return result
}
// 五:分页查询
var FenYe=async function(page,pageSize){
// 先查出所有数据
var allFood=await userModel.find()
// 然后得出查询结果数组的长度
var allCount=await allFood.length
// 每一页的数据
var result=await userModel.find().skip((page-1)*pageSize).limit(pageSize-0)
return {result,allCount,page}
}
// 六:分类查询
var FenLei=async function(foodType){
var result=await userModel.find({foodType})
return result
}
// 七:模糊搜索
var MoHu=async function(kw){
// 通过正则表达式匹配相关的关键字,如下是我们定义的正则
var regex=new RegExp(kw)
// $regex表示可以写一个正则表达式
// name:{$regex:regex}表示如果数据库内部所有数据中,如果name属性满足有关键字为kw的就会查找到
// 现在我们使用并集查询配合正则去实现name和foodType同时都有的模糊搜索封装
var result=await userModel.find({$or:[{name:{$regex:regex}},{foodType:{$regex:regex}}]})
return result
}
module.exports = {
insertFood,
findFood,
delFood,
xiuGai,
FenYe,
FenLei,
MoHu
}
foodRouter.js
var express = require("express")
var userModel = require("../mongoose模块的使用/userModel")
var router = express.Router()
var {insertFood,findFood,delFood,xiuGai,FenYe,FenLei,MoHu} = require("../mongoose模块的使用/mongoose增删改查封装")
// 接口文档注释
/**
* @api {post} http://localhost:3210/api/add 这个是管理平台添加菜品的接口
* @apiName add
* @apiGroup Food
* @apiParam {String} name name这个参数是用来表示菜名的
* @apiParam {String} price price这个参数是用来表示菜品的价格
* @apiParam {String} desc desc这个参数是用来表示对菜品的相关描述用的
* @apiParam {String} img img这个参数是用来表示菜品的照片
* @apiParam {String} foodType foodType这个参数是用来描述这个菜品的分类
* @apiSuccess {String} err err表示返回的是状态码
* @apiSuccess {String} msg msg表示返回的是查询信息
*/
// 1.添加菜品
router.post("/add", (req, res) => {
//接收数据
var {name,price,desc,img,foodType} = req.body
//处理数据 ,插入数据库
//返回数据
userModel.insertMany({name,price,desc,img,foodType})
.then(function (data) {
res.send(`{err:1,msg:"添加菜品成功,祝您用餐愉快!","您添加的菜为":${data}}`)
}, function (sb) {
res.send({
err: -1,
msg: "添加菜品失败,请重新添加!"
})
})
})
// 这个接口如果传入数据库的某个信息,就会根据新信息去查找
// 如果不传入数据库已有的信息,就查找整个数据库
// 二:查询菜品
router.post("/cha", (req, res) => {
console.log("1", req.body);
findFood(req.body, res)
})
// 三.删除菜品
router.post("/del", (req, res) => {
var {_id} = req.body
delFood(_id)
.then((data) => {
res.send(`菜品删除成功!`)
})
.catch((err) => {
console.log(err);
res.send("菜品删除失败!")
})
})
// 修改数据
router.post("/xg",(req,res)=>{
var {_id,name,price,img,desc,foodType}=req.body
xiuGai(_id,{name,price,img,desc,foodType})
.then(()=>{
res.send({err:0,msg:"修改成功!"})
})
.catch((err)=>{
res.send({err:-1,msg:"修改失败请重试!"})
})
})
// 分页查询
router.post("/fy",(req,res)=>{
var page=req.body.page||1//查询的第几页数据
var pageSize=req.body.pageSize||2//每页多少天数据
console.log(page,pageSize);
FenYe(page,pageSize)
.then((data)=>{
var {result,allCount,page}=data
// maxPage为最大页数.
var maxPage=Math.ceil(allCount/page)
res.send({err:0,msg:"查询成功!",result,allCount,maxPage})
})
.catch((err)=>{
res.send({err:-1,msg:"查询失败请重试!"})
})
})
// 分类查询
// 分类查询的数据可能很多,所以后面我们需要和分页查询做关联.
router.post("/fl",(req,res)=>{
var {foodType}=req.body
FenLei(foodType)
.then((data)=>{
res.send({err:0,msg:"分类查询成功!",list:data})
})
.catch((err)=>{
res.send({err:-1,msg:"分类查询失败,请重试!"})
})
})
// 模糊搜索/部分关键字或则关键字查询。
// 接口作用,比如我输入一个字,我们去数据库搜索有没有和关键字相关的数据内容.
// 由于模糊搜索,非常有可能一个关键字查询出很多条数据,所以我们要和分页接口做关联.
router.post("/mh",(req,res)=>{
// kw是你要传入关键字的,字段属性名
var {kw}=req.body||""
MoHu(kw)
.then((data)=>{
if(data.length!=0){
res.send({err:0,msg:"关键字查询成功!",list:data})
}else{
res.send({err:0,msg:"关键字查询失败,您搜索的菜品我们厨子还不会做呢★.★"})
}
})
.catch((err)=>{
res.send({err:-1,msg:"关键字查询失败,请重试!"})
})
})
module.exports = router
server.js
var express=require("express")
var bodyParser=require("body-parser")
var path=require("path")
var fs=require("fs")
var app=express()
// post数据的解析
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(path.join("./public")))
// 把暴露的函数赋值给了connect变量
require("./mongoose模块的使用/connect")
// 如果connect文件不是用函数封装并且没有抛出,打印connect这个变量会出undefined,这样引入表示直接执行一次connect这个js文件的代码
// 抛出/暴露,是为了多次使用,比如函数,多次调用
// 我们做了函数封装并且做了模块暴露
// 如果用作函数封装的时候我们需要用变量去接,然后变量()才能调用函数
var userRouter=require("./router/loginAndReg")
var upLoad=require("./router/upLoad")
var foodRouter=require("./router/foodRouter")
app.use("/api",userRouter)
// app.use("/api",upLoad)
app.use("/api",foodRouter)
app.listen(3210,()=>{
console.log("服务器端口号3210已经成功开启!","佛祖保佑无我写的代码一切安好无bug");
})
apidoc.json
{
"name": "帅气的张亿同学为你们留下的api使用文档",
"version": "0.1.0",
"description": "千万别羡慕我超级帅,可以迷倒万千女性的那种帅。",
"title": "叽叽歪歪的★★",
"url" : "http://localhost:3210"
}
管理系统的需求分析以及apidoc插件生成接口文档
// 管理平台功能需求
// 1.添加菜品
// 2.删除菜品
// 3.修改菜品
// 4.查询菜品
// 分页查询
// 模糊查询
// 分类查询
// 通过apidoc 插件生成接口文档
// 将代码注释(必须符合规范)变成接口
// 接口文档注释插件补充知识
/**
* @api {get} /user/:id Request User information
* @apiName GetUser
* @apiGroup User
*
* @apiParam {Number} id Users unique ID.
*
* @apiSuccess {String} firstname Firstname of the User.
* @apiSuccess {String} lastname Lastname of the User.
*/
// 1. * @api {get} /user/:id Request User information→这段api注释表示你发起的请求是什么请求,以及接口路径,还有你对这个接口的注释
// 使用注释模板注释的使用实例如下👇
// * @api {get} http://localhost:3210/api/add 这个是管理平台添加菜品的接口
// 2. * @apiName GetUser 这段api注释表示你的接口叫什么名字
// 使用注释模板注释的使用实例如下👇
// * @apiName add
// 3. * @apiGroup User 这段api注释表示你的接口属于什么分组
// 使用注释模板注释的使用实例如下👇我们将它设置为食物分组Food
// * @apiGroup Food
// 4. * @apiParam {Number} id Users unique ID. 这段api注释表示你写的这个接口需要那几个参数,参数分别是什么,需要几个参数我们就把这段代码写几遍
// @apiParam {Number}中的Number表示你这个接口的参数要填的是什么数据类型,比如String等等
// 使用注释模板注释的使用实例如下👇【因为这个接口需要用到五个参数,他们分别是name,price,desc,img,foodType】,我们每一个参数都要写一次api注释模板
// * @apiParam {String} name name这个参数是用来表示菜名的
// * @apiParam {String} price price这个参数是用来表示菜品的价格
// * @apiParam {String} desc desc这个参数是用来表示对菜品的相关描述用的
// * @apiParam {String} img img这个参数是用来表示菜品的照片
// * @apiParam {String} foodType foodType这个参数是用来描述这个菜品的分类
// 5. * @apiSuccess {String} firstname Firstname of the User.这段api注释表示你写的这个接口访问之后会返回什么。比如返回的是对象
// 使用注释模板注释的使用实例如下👇
// * @apiSuccess {String} err err表示返回的是状态码
// * @apiSuccess {String} msg msg表示返回的是查询信息
// 我们写完这些api接口注释模板之后,把代码合并起来放在我们接口的上面
// 如下综合实力(我们将注释放在了接口的上方)👇
// 接口文档注释
/**
* @api {get} http://localhost:3210/api/add 这个是管理平台添加菜品的接口
* @apiName add
* @apiGroup Food
* @apiParam {String} name name这个参数是用来表示菜名的
* @apiParam {String} price price这个参数是用来表示菜品的价格
* @apiParam {String} desc desc这个参数是用来表示对菜品的相关描述用的
* @apiParam {String} img img这个参数是用来表示菜品的照片
* @apiParam {String} foodType foodType这个参数是用来描述这个菜品的分类
* @apiSuccess {String} err err表示返回的是状态码
* @apiSuccess {String} msg msg表示返回的是查询信息
*/
// 我们在接口上写好了注释后,我们就开始下载这个插件
// 在cmd当中输入
// npm install apidoc -g
// 进行全局安装apidoc插件
// 接着我们创建一个 apidoc.json 的文件注意是apidoc.json的文件一个字母都不能错必须是apidoc.json
// 把apidoc.json的文件夹建立在和你的服务器同级的位置
// 建立好apidoc.json文件之后把如下👇代码复制到apidoc.json文件上
// {
// "name": "example",
// "version": "0.1.0",
// "description": "apiDoc basic example",
// "title": "Custom apiDoc browser title",
// "url" : "https://api.github.com/v1"
// }
// 声明一下上面赋值的代码如何修改
// name填的是你的api文档叫什么名字,比如我们填"帅气的某某某为你们留下的api使用文档"
// description填的是你的api文档的描述,比如我们写"千万别羡慕我超级帅,以及迷倒万千女性的那身材与腹肌。"
// title,写标题,你可以随便写
// url写你服务器的地址比如"http://localhost:3210"
// 安装完成并且对apidoc.json文件内部的信息修改好之后,我们就可以使用如下👇编译指令👇
// 如下的指令一定要在apidoc.json文件的目录下打开cmd执行
// apidoc -i myapp/ -o apidoc/ -t mytemplate/
// apidoc -i myapp/ -o apidoc/ -t mytemplate/指令的意思,
// myapp/表示的是你写注释的文件夹位置,如上我们的例子是把注释写在了foodRouter.js的文件下
// 因为foodRouter.js属在于router文件目录下,所以我们要填相对于apidoc.json文件的路径./router
// -o右边的写的是aip文档的导出目录,如果目录不存在它会自动帮你新建一个目录
// apidoc -i ./router -o ./doc
如上生成了index.html文件打开index.html文件里面就是我们生产的接口文档