Коа + mongodb бой

koa
Коа + mongodb бой

Коа строительные леса

Я сделал скаффолд koa, представляющий собой комбинацию koa и mongodb, и загрузил его на GitHub.

портал

Структура каталогов такая же, как и выше, контроллер(то есть там, где написан код), журнал, модель базы данных, маршрут, инструмент и файл записи.

Чтобы написать код, просто добавьте маршруты и заполните контроллер, как показано на рисунке.

Какие составляющие анализа ниже 👇

koa

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

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

app.listen(3000);

узнать большеРамка коа Руан Ифэн

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 Controllers = require('./controller')({})

const dateNumberController = Controllers('date_number')

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

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

// routers/controller.js
const controllerFunction = ({basePath = '../controllers/', router_path_function}) => (controllerName) => {
    const divController = require([basePath, controllerName].join(''))
    const prefix = controllerName
    class Controller extends divController {
        prefix = ''
        getPath(name){
            return router_path_function ? router_path_function(this.prefix, name) : `/${this.prefix}/${name}`
        }
    }
    const controller = new Controller()
    controller.prefix = prefix
    return controller
}

module.exports = controllerFunction

// controllers/date_number.js
见下面的 mongodb 里面的模型代码

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

Подробнее см.koa-router github

bodyparser

С маршрутизацией, но нам также нужны параметры, передаваемые из внешнего интерфейса, поэтому нам нужно сначала получить параметры

пример

app.use(async ctx => {
  ctx.body = ctx.request.body;
});

В это время почтовый запрос может быть проанализирован, является ли он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, затем установите npmmongoose, можно инициализировать следующим образом

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 первичный ключ первичный ключ, MongoDB автоматически устанавливает поле _id в качестве первичного ключа

Для MAC нужно сначала запустить mongod, а потом открыть окно, иначе напомнит, что сервис не найден; В Windows есть собственное программное обеспечение для визуализации, и установленный компас mongoDB можно проверить во время установки.

to function

Выше приведен код, который используется для

to — это инкапсуляция обещания в форме [err, data], которая имеет то преимущество, что не нужно писать try catch и обрабатывать ошибки горизонтально.

to является глобальным, представленным в main.js

Передовой

Пейджинговый запрос

new DateNumber.find().skip(条数*(页码-1)).limit(条数)

Будет медленно, если индекс не установлен

даже левый заданный запрос

db.orders.aggregate([
   {
     $lookup:
       {
         from: "inventory",
         localField: "item",
         foreignField: "sku",
         as: "inventory_docs"
       }
  }
])

Подключить стол, чтобы узнать больше

журнал

использоватьlog4jsЖурнал реализации

Как использовать

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

Level

Роль уровня состоит в том, чтобы выводить >= лог текущего уровня

выходные настройки

Что я установил, так это то, что информация выводится нормально, а вывод делится по дате (чтобы файл не был слишком большим), если есть большая проблема, такая как ошибка, отправьте электронное письмо, пример такой: включая тестовый код, вы настраиваете учетную запись в электронной почте пароль и он работает

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 уровень, спасибо

-- над --