Koa+mongodb实战

2020/5/12 11:26:21

本文主要是介绍Koa+mongodb实战,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

koa 脚手架

本人弄了一个koa脚手架,koa和mongodb组合而成, 已上传GitHub. 👏 👏 👏 👏

传送门

目录结构如上,一个控制器(也就是写代码的地方),一个日志,一个数据库模型,一个路由,一个工具,和入口文件。

写代码只要添加路由 填充控制器就好了,如图所示

下面解析下有哪些构成的👇

koa

const Koa = require('koa');
const app = new Koa();

// response
app.use(ctx => {
  ctx.body = 'Hello Koa';
});

app.listen(3000);
复制代码

更多见阮一峰koa框架

router

官方例子

var Koa = require('koa');
var Router = require('koa-router');

var app = new Koa();
var router = new Router();

router.get('/', (ctx, next) => {
  // ctx.router available
});

app
  .use(router.routes())
  .use(router.allowedMethods());
复制代码

实战例子

// routers/index.js

const Router = require('koa-router')
const dateNumberController = require('../controllers/date_number')

const router = new Router({
	prefix: '/api'
})

dateNumberController.prefix ='date_number'

router
.post(dateNumberController.getPath('add'), dateNumberController.add)
.get(dateNumberController.getPath(`select`), dateNumberController.find)
.post(dateNumberController.getPath(`remove`), dateNumberController.delect)
.post(dateNumberController.getPath(`update`), dateNumberController.update)

module.exports = router

// main.js
const router = require('./routers')
app.use(router.routes());
复制代码

更多详情见koa-router github

bodyparser

有了路由,但是我们还需要前端传递过来的参数,所以需要先获取参数

例子

app.use(async ctx => {
  ctx.body = ctx.request.body;
});
复制代码

这时候post请求就可以解析了,不管是application/json还是application/x-www-form-urlencoded

效果

更新详情见bodyparser GitHub

koa-parameter

拿到参数后我们需要校验它

// main.js
const parameter = require("koa-parameter")
const error = require("koa-json-error")

app.use(parameter(app));
// 这个是json错误处理,可以自动抛出http status 422
app.use(
    error({ postFormat: (e, { stack, ...rest }) => ({ stack, rest }) })
)

// ctx里面,比如路由里面
ctx.verifyParams({
    date: { type: "string", required: true },
    list: { type: "array", required: true },
})
复制代码

mongodb

拿到参数,我们下一步就是需要操作数据了

初始化

安装mongodb,然后npm安装mongoose, 如下初始化即可

const mongoose = require('mongoose')
// db是数据库名称哦,没有的话会自动创建
const DB_ADDRESS = "mongodb://localhost:27017/db"
mongoose.connect(DB_ADDRESS, {useNewUrlParser: true, useUnifiedTopology: true}, err => {
    if (err) {
        log.fatal({msg: '[Mongoose] database connect failed!', err})
    } else {
        console.log('[Mongoose] database connect success!')
    }
})
module.exports = mongoose
复制代码

建立模型

使用的时候,我们需要先建立集合(在mysql里面叫表),但是MD更灵活,可以直接在代码里面操作,我们先建立模型。

const mongoose = require('mongoose');  
const { Schema, model } = mongoose;

// 数据模型  
let DateNumberSchema = new Schema({
    date: { type: String, required: true, unique: true },
    list: { type: Array, require: true },
});

module.exports = model('DateNumber', DateNumberSchema);
复制代码

操作数据库

const data = await DateNumber.find()
复制代码

新增

// 要和模型对应
const data = await to( new DateNumber({date, list}).save() 
复制代码

const data = await DateNumber.deleteOne({date: date})
复制代码

const data = await DateNumber.updateOne({date}, {$set: {list}})
复制代码

例子

const DateNumber = require('../models/dateNumber')

class DateNumberController {
    prefix = ''
    getPath(name){
        return `/${this.prefix}/${name}`
    }
    async add(ctx, next){
        ctx.verifyParams({
            date: { type: "string", required: true },
            list: { type: "array", required: true },
        })
        const {date, list} = ctx.request.body
        const [err, data] = await to( new DateNumber({date, list}).save() )
        if(err) return ctx.throw(500, err)
        ctx.response.body = data
    }
    async find(ctx, next){
        const data = await DateNumber.find()
        ctx.response.body = data.join('\n')
        log.info('find')
    }
    async delect (ctx, next){
        ctx.verifyParams({
            date: { type: "string", required: true },
        })
        const {date} = ctx.request.body
        const data = await DateNumber.deleteOne({date: date})
        ctx.response.body = data
    }
    async update(ctx, next){
        ctx.verifyParams({
            date: { type: "string", required: true },
            list: { type: "array", required: true },
        })
        const {date, list} = ctx.request.body
        const [err, data] = await to( DateNumber.updateOne({date}, {$set: {list}}) )
        if(err) return ctx.throw(500, err)
        ctx.response.body = data
    }
}

module.exports = new DateNumberController()
复制代码

对应关系(来自菜鸟教程)

SQL术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键

MAC的需要先运行mongod,然后再开一个窗口,不然会提醒找不到服务; Windows有自带的可视化软件,安装的时候install mongoDB compass勾上即可

to function

上面有一个代码用到了to

to是对promise的一个封装,变成[err, data] 这种形式,这样有一个好处是不需要写try catch,又可以平级处理错误。

to是全局的,在main.js引入

mongodb更多见菜鸟教程

日志

使用log4js实现日志

使用方式

var log4js = require('log4js');
var logger = log4js.getLogger();
logger.level = 'debug';
logger.debug("Some debug messages");
复制代码

Level

等级作用是,输出>=当前级别的日志

输出设置

我设置的是,info正常输出,输出的时候按日期分(这样文件不会太大),如果遇到error这种大问题就发邮件,例子如下,包含测试代码,你配置下email里面的账号密码就可以运行了

const config = {
    // 例子
    email: {
        host: 'smtp.qq.com',
        auth: {
            user: '你的qq号@qq.com',
            pass: '你的密码,',
        },
        recipients: '发送方@126.com'
    }
}

const LOGINFO = {
    appenders: {
        info: {
            type: "DateFile",
            category: 'dateFileLog',
            filename: path.join(__dirname, './log/info/'),
            pattern: "yyyy-MM-dd.log",
            alwaysIncludePattern: true
        },
        email: {
            type: '@log4js-node/smtp',
             //发送邮件的邮箱
            sender: config.email.auth.user,
             //标题
            subject: 'Latest error report',
            SMTP: {
                host: config.email.host, 
                auth: config.email.auth,
            },
            recipients: config.email.recipients
        }
    },
}
const log4js = require('log4js')
log4js.configure(LOGINFO)

const log_info = log4js.getLogger()
const log_error = log4js.getLogger('error')

global.log = {
    debug: log_info.debug.bind(log_info),
    info: log_info.info.bind(log_info),
    warn: log_info.warn.bind(log_info),
    error: log_error.error.bind(log_error),
    fatal: log_error.fatal.bind(log_error),
}

// 这个是测试代码
setTimeout(() => {
    log.fatal({
        msg: '测试',
        err: 'fatal'
    })
}, 400)
复制代码

邮箱密钥获取方式: 进入qq邮箱,设置----> 账户 ------->开启服务:POP3/SMTP服务 ----->生成授权码

log.fatal({
        msg: '测试',
        err: 'fatal'
})
复制代码

效果

log4js更多详情见 log4js github
log4js邮箱更多详情见 log4js-node/smtp github

其他

各位大哥哥小姐姐麻烦点个赞,我要冲3级,谢谢

-- 完 --



这篇关于Koa+mongodb实战的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程