本文原创 ,转载请标明出处
1 koa的基本使用
koa是基于node平台的web开发框架
使用koa去创建一个服务器
const Koa = require('koa') // bodyParser 处理post请求 const bodyParser = require('koa-bodyparser') const port = 7001 const app = new Koa() app.use(bodyParser()) app.use(async ctx => { ctx.body = 'hello , i am first koa applicance' }) app.listen(port)
koa 使用 下面方式 利用ctx.body将内容或接口数据返回给到页面,若作为接口时,未写ctx.body接口将报错404 Not Found
app.use(async ctx => { ctx.body = '' })
下面一个从后台获取数据返回给到页面 的demo(作为中间层)
const Koa = require('koa') // bodyParser 处理post请求 const bodyParser = require('koa-bodyparser') // 用于请求后台数据 当我们想把改服务作为web和后台的中间层时 需要使用request-promise 或者request 当然还有其他的 const request = require('request-promise') const port = 7001 const app = new Koa() app.use(bodyParser()) // 向后台发起请求 let _callApi = (url, datas, headers) => { // 本文以POST请求为例说明,其他方式请参阅request-promise官方文档 let options = { uri: url, method: 'POST', body: datas, json: true, timeout: 10000 } if (headers) { options.headers = headers } return new Promise((resolve, reject) => { request(options) .then(res => { resolve(res) }) .catch(err => { reject(err) }) }) } app.use(async ctx => { ctx.body = 'hello , i am first koa applicance' }) app.use(async ctx => { let queryUrl = ctx.request.url.split('?')[0] if (queryUrl === '/mytest/testpost') { let data = ctx.request.body let response = await _callApi('apiUrl', data) ctx.body = response } }) app.listen(port)
使用 ctx.request 将web端请求的内容拿到,根据自己的需求组装 将内容发送给后台获取接口数据 可以自行打印ctx.request
注意:A 当在项目中使用session时 需要有配置文件并且给app设置keys
// 存储 内容 const CONFIG = { overwrite: false, maxAge: 7200000 //过期时间设置两个小时 } app.keys = ['myvars is changing'] app.use(session(CONFIG, app)) // 在接口中存数据 ctx.session.username = 'myName' // 在接口中去数据 let userName = ctx.session.username
B:项目中使用cookies
const Koa = require('koa'); const app = new Koa(); app.use(async ctx=>{ if(ctx.url === '/public'){ ctx.cookies.set( 'name', 'public', { domain: 'localhost', path: '/public', // 有效时长 表示从Date.now()得到的毫秒值 maxAge: 24 * 60 * 60 * 1000, // cookies 过期的date expires: new Date('2018-12-31'), // 服务器可访问cookie 默认true httpOnly: false, // 是否覆盖以前设置的同名的cookie默认false overwrite: false } ); ctx.body = 'cookie success'; }else{ ctx.body = 'no cookie'; } }); app.listen(3000, () => { console.log('服务开启成功在3000端口'); });
当然 当我们接口很多时 可以使用koa-router进行路由的定义 ,koa-router支持很多接口方式
router.get('/users', ctx => { // .... }) router.post('/users', ctx => { // .... }) .put('/user/:id', ctx => { // .... }) .del('/user/:id', ctx => { // .... }) .all('/user/:id', ctx => { // .... });
koa-router 引入方式:
const Router = require('koa-router') const router = new Router() //或者下面的方式 const router = require('koa-router')()
// router装载 routes代表可能多个 app.use(router.routes()); // 如get 就只能用get进行请求 使用post将会报错405 Method Not Allowed; app.use(router.allowedMethods());
2 mongodb 的基本用法
mongodb的安装请参见菜鸟教程:https://www.runoob.com/mongodb/mongodb-window-install.html 或者参见其他
(安装教程不同的是现有的 安装包下载完直接默认了 data和log的存放地址 可以自定义修改), 安装完成可以通过mongod 命令查看
开始使用:命令行输入 mongo 之后就可以进行增删改查;
也可以在当前bash目录下写js文件 去连接数据库进行增删改查;执行命令 load(‘文件名’),比如dboper.js:
var userName = "testtwo"; var time = Date.parse(new Date()); var data = { "title": userName, "registTime": time }; var db = connect('testtwo'); db.testtwo.insert(data); print('insert success');
use testone switched to db testone db testone db.dropDatabase() { "dropped" : "testone", "ok" : 1 }
//数据查询find $gte: 大于等于 $lte: 小于等于 db.user.find( // 查询条件 {age: {$gte: 20, $lte: 30}}, // 显示的字段名称 {name: true, age: true, _id: false} ) $in: 数组内等于20和等于25 db.user.find( {age: { $in: [20, 25]}}, //等于20 和25的 {name: true, age: true, _id: false} ) $or $and db.user.find({ $and/$or: [ {age: { $gte: 20}}, {'pc.brand': 'IBM'} ]}, {name: true, age: true, _id: false} ) db.user.find( // hobby中包含篮球 {hobby: '篮球'}, // hobby只是篮球, // {hobby: ['篮球']}, {name: true, age: true, _id: false} ); $all 如下既喜欢篮球又喜欢敲代码 若为$in则是或的关系 db.user.find( {hobby: {$all: ['篮球', '敲代码']}}, {name: true, age: true, _id: false} ); $size 按照数组的长度去查询 db.user.find( {hobby: {$size: 3}}, {name: true, age: true, _id: false} ); limit 每次查询多少条 skip 跳过多少条 sort 按那个字段进行排序 1和-1 db.user.find( {}, {name: true, age: true, _id: false} ).limit(1).skip(1).sort({age: -1})
数据更新 $set 修改指定的可以值 db.myColl.update({ name:'lxh' },{ $set:{ 'age':18 }}) $unset 删除一个keyvalue值 name=lxh这条数据里面将没有age这个key和value值 db.myColl.update({ name:'lxh' },{ $unset:{ 'age': ''}}) upsert(更新插入) 比如下面有age值就去更新,没有就去插入这个值 db.myColl.update({ name:'lxh' },{ $set:{ age:18 }},{upsert:ture}) multi 所有文档都加上hobby属性,multi:false只有第一条数据会加 db.myColl.update({},{$set:{hobby:['code']}},{multi:true}) $push 给文档里面的某个属性push内容,需要时数组格式 db.myColl.update({name:'lxh'},{$push:{hobby:'chiji'}}) $addToSet 查找内容是否已存在,存在了就不加,不存在就push db.myColl.update({name:'lxh'},{$addToSet:{hobby:'sleep'}}) $each db.myColl.update({name:'lxh'},{$addToSet:{hobby:{$each:['sleep','wake up']}}}) $set db.myColl.update({name:'lxh'},{$set:{'hobby.0':'sport'}}) findAndModify 查找并且修改(上面不会返回任何内容,该方法应答式的) var modify = { findAndModify: 'user', //应答式的,会返回操作结果 query: {name: 'lxh'}, update: {$set: {age: 22}}, new: true //true 更新后的结果,false更新前的结果 };
3 koa 连接mongodb 进行连接数据库并增删改查,mongoose是Node和MongoDB数据通讯的数据建模库
npm install mongoose --save
A 使用mongoose.connect连接数据库
const mongoose = require('mongoose') //testone 是自己建的db const DB_URL = 'mongodb://127.0.0.1:27017/testone' mongoose.connect(DB_URL, { useNewUrlParser: true, useUnifiedTopology: true }) var db = mongoose.connection db.on('connected', function() { console.log('Mongoose connection open to ' + DB_URL) }) // 连接异常数据库报错 db.on('error', function(err) { console.log('Mongoose connection error:' + err) }) // 连接断开 disconnected 连接异常断开 db.on('disconnected', function() { console.log('Mongoose connection disconnected') }) module.exports = mongoose
注意:连接数据库时 不设置 useNewUrlParser: true,useUnifiedTopology: true 会导致报错 过时的 告诉你需要通过设置这个 来进行兼容
B 使用mongoose.Schema 去创建数据表里面的各个字段和类型,每个mongoose都是从Schema开始,映射到MongoDB集合
const Schema = mongoose.Schema
const testSchema = new Schema({
name: String,
age: Number,
studentId: { type: String, unique: true } //设置了unique 为true新建时传入重复的值会提示E11000 duplicate key error collection***
})
C 使用Model 将Schema 和底层MongoDB数据库连接到一起,model的实例就是文档,model负责从底层MongoDB数据库创建和读取文档
const Student = mongoose.model('testone', testSchema)
D 创建自己的类 封装增删改查功能
class StudentDb { constructor() {} // 查询 query(obj) { return new Promise((resolve, reject) => { Student.find({}, (err, res) => { // Student.find({ age: { $gte: 22, $lt: 25 } }, (err, res) => { //按条件去查询 if (err) { reject(err) } resolve(res) }) .limit(obj.pageSize) // 限制访问的数量 .skip(obj.pageSize * (obj.pageNum - 1)) // 跳过多少去访问 用此可以实现分页的效果 .sort({ age: 1 }) //1 按age升序排列, -1 按降序排列 }) } // 保存 save(obj) { const m = new Student(obj) return new Promise((resolve, reject) => { m.save((err, res) => { if (err) { reject(err) } resolve(res) console.log(res) }) }) } // 按studentId查询 where(obj) { const query = JSON.parse(JSON.stringify(obj)) return new Promise((resolve, reject) => { Student.find({ studentId: query.studentId }, (err, res) => { if (err) { reject(err) } resolve(res) }) }) } // 更新 update(obj) { const query = JSON.parse(JSON.stringify(obj)) return new Promise((resolve, reject) => { Student.updateOne({ _id: query._id }, { $set: query }, (err, res) => { if (err) { reject(err) } resolve(res) console.log('update=====', res) }) }) } // 删除 del(obj) { const query = JSON.parse(JSON.stringify(obj)) return new Promise((resolve, reject) => { Student.remove({ studentId: query.studentId }, (err, res) => { if (err) { reject(err) } resolve(res) console.log(res) }) }) } }
E 导出这个类在其他的地方使用
module.exports = new StudentDb()
F 在需要的文件中引入 并使用
const StudentDb = require('./index') //上面类定义的文件
G 利用koa-router 以及上面封装的方法进行数据库的操作
// 查询所有内容接口 router.get('/testMogodb/query', async ctx => { // const queryPars = ctx.request.body const queryPars = { pageSize: ctx.request.body.pageSize, pageNum: ctx.request.body.pageNum } let data = await StudentDb.query(queryPars) ctx.body = data }) // 按条件查询接口 router.post('/testMogodb/search', async ctx => { const queryPars = ctx.request.body console.log('queryPars', queryPars) let data = await StudentDb.where(queryPars) ctx.body = data }) // 添加接口 router.post('/testMogodb/add', async ctx => { const studentObj = { name: ctx.request.body.name, age: ctx.request.body.age, studentId: ctx.request.body.studentId } let code, message try { await StudentDb.save(studentObj) code = 0 message = 'Add successful' } catch (error) { code = -1 message = error || 'Add failure' } ctx.body = { code, message } }) // 更新已有内容的接口 router.post('/testMogodb/update', async ctx => { let code, message const result = await StudentDb.update({ name: ctx.request.body.name, age: ctx.request.body.age, studentId: ctx.request.body.studentId, _id: ctx.request.body._id }) try { await result code = 0 message = 'Update successful' } catch (error) { code = -1 message = error || 'Update failure' } ctx.body = { code, message } }) // 删除指定内容接口 router.post('/testMogodb/del', async ctx => { const studentObj = { // _id: ctx.request.body._id studentId: ctx.request.body.studentId } let code, message try { await StudentDb.del(studentObj) code = 0 message = 'Delete successful' } catch (error) { code = -1 message = error || 'Delete failure' } ctx.body = { code, message } })
注意 上面router使用过程中 async await 语法的使用;
详细代码地址:https://github.com/liangxianh/koa-mongoose.git