专栏首页与前端沾边Koa入门(四)Koa 操作数据库
原创

Koa入门(四)Koa 操作数据库

1 NoSql 简介

我们使用 koa 开发后台,最常用的数据库就是 mongodb,这是 NoSql 数据库类型的一种,那什么是 NoSql 呢?首先需要说的是,NoSql 并不表示 NO SQL 没有 SQL 的意思。实际上,它是 Not Only SQL 的缩写。它的意义是:适用关系型数据库的时候就使用关系型数据库,不适用的时候也没有必要非使用关系型数据库不可,可以考虑使用更加合适的数据存储

关系型数据库中的表都是存储一些结构化的数据,每条记录的字段的组成都一样,即使不是每条记录都需要所有的字段,但数据库会为每条数据分配所有的字段。而非关系型数据库以键值对 (key-value) 存储,它的结构不固定,每一条记录可以有不一样的键,每条记录可以根据需要增加一些自己的键值对,这样就不会局限于固定的结构,可以减少一些时间和空间的开销。

1.1 NoSql数据库优缺点

  • 在优势方面主要体现在下面几点:
    • 简单的扩展
    • 快速的读写
    • 低廉的成本
    • 灵活的数据模型
  • 在不足方面主要有下面几点:
    • 不提供对SQL的支持
    • 支持的特性不够丰富
    • 现有的产品不够成熟

2 Mongoodb

MongoDB 使用 C++ 语言编写的非关系型数据库。特点是高性能、易部署、易使用,存储数据十分方便。

2.1 主要特性

  • 面向集合存储,易于存储对象类型的数据
  • 模式自由
  • 支持动态查询
  • 支持完全索引,包含内部对象
  • 支持复制和故障恢复
  • 使用高效的二进制数据存储,包括大型对象
  • 文件存储格式为 BSON (一种 JSON 的扩展)

3 Mongodb 安装

有两种安装方式

3.1 Mongodb Atlas

一种是使用 mongodb atlas,官网注册完,直接本地连接就可以了。缺点是需要文明上网,通常连上了也是很慢。注册地址,教程可以参考这里

另一种是安装到本地(我的是windows10,本地快啊),直接安装 msi,启动后直接连接,大家可以自行网上搜索安装。下载地址

4 Koa + Mongodb 操作

4.1 安装链接

  • npm i mongoose -Sconst mongoose = require('mongoose') // 默认 27017 端口 mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true }, () => console.log('数据库连接成功')) mongoose.connection.on('error', console.error)像链接地址、端口配置我们最好单独放在配置文件中,更好的维护// app/config.js module.exports = { connectionStr: 'mongodb://localhost:27017/test' }
  • app/index.js 引入
  • 启动 mongoodb 服务
  • 启动 Koa 服务

可以看到 koa 链接数据库成功

4.2 创建 user modal

  • 新建 app/models/user.js (使用复数),建立模型const mongoose = require('mongoose') const { Schema, model } = mongoose // 通过 schema 设计出表结构,简单结构复杂结构都可以,每一条自动创建 _id const userSchema = new Schema({ name: { type: String, required: true // 必要 }, password: { type: String, required: true } }) // User 表 module.exports = model('User', userSchema)
  • 操作数据库实现增删改查功能

把我们创建的模型引入到上一节中创建的控制器中

const User = require('../models/user')

class UsersCtl {
  // 获取用户列表
  async find(ctx) {
    // 操作数据库一定要 await
    ctx.body = await User.find()
  }
  // 根据 id 查找某一个用户
  async findById(ctx) {
    ctx.body = await User.findById(ctx.params.id)
  }
  // 创建用户
  async create(ctx) {
    ctx.body = await new User(ctx.request.body).save()
  }
  // 更新用户信息
  async update(ctx) {
    const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body)
    ctx.body = user
  }
  // 删除用户
  async delete(ctx) {
    const user = await User.findByIdAndRemove(ctx.params.id)
    ctx.body = user
  }
}

module.exports = new UsersCtl()

我们先新增用户再获取和删除,方便测试,使用 postman 测试如下:

增加:

获取列表:

获取某人:

删除某人:

更新用户信息:

4.3 优化逻辑

我们在操作数据库前一定要判断数据的正确性,例如增加要判断是否已有重名,修改要判断是否有这个用户,一些操作还需要权鉴等等。

  • 使用 koa-parameter 进行参数校验 npm i koa-parameter -Sapp/index.js ... const parameter = require('koa-parameter') ... // 校验请求体的,放在后面 app.use(parameter(app)) // 上下文 ctx 增加个方法,全局校验
  • 增删改查增加判断 大家可自行使用 postman 测试以下代码const User = require('../models/user') class UsersCtl { // 获取用户列表 async find(ctx) { // 操作数据库一定要 await ctx.body = await User.find() } // 根据 id 查找某一个用户 async findById(ctx) { const user = await User.findById(ctx.params.id) if (!user) { ctx.throw(404, '用户不存在') } else { ctx.body = user } } // 创建用户 async create(ctx) { // 中间库全局方法校验参数 ctx.verifyParams({ name: { type: 'string', required: true }, password: { type: 'string', required: true } }) // 判断库中是否已存在用户名 const { name } = ctx.request.body const user = await User.findOne({ name }) if (user) { ctx.throw(409, '用户名已存在') } ctx.body = await new User(ctx.request.body).save() } // 更新用户信息 async update(ctx) { ctx.verifyParams({ name: { type: 'string', required: true }, password: { type: 'string', required: true } }) const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body) if (!user) { ctx.throw(404, '用户不存在') } ctx.body = user } // 删除用户 async delete(ctx) { const user = await User.findByIdAndRemove(ctx.params.id) // 删除后,会先把原来的返回下 if (!user) { ctx.throw(404, '用户不存在') } ctx.body = user } } module.exports = new UsersCtl()

5 mongoodb 其他操作

  • 我们看到列表中有返回密码字段,这是不合适的,容易泄露,所以需要在模型中隐藏。如果需要的话可以在查表时使用 select 关键字password: { type: String, required: true, select: false // 不会返回 } await User.find().select(‘+password’)通常使用 Koa 会在前端使用 fields 字段,后台通过该字段相应返回隐藏字段前端传入格式:password;name;age, ? 拼接 url 后面 // 获取用户列表 async find(ctx) { const { fields = '' } = ctx.query const selectFields = fields.split(';').filter(f => f).map(f => ' +' + f).join('') // 操作数据库一定要 await ctx.body = await User.find().select(selectFields) }async find(ctx) { let { fields = '', page = 1, limit = 10 } = ctx.query const selectFields = fields.split(';').filter(f => f).map(f => ' +' + f).join('') // page 和 limit 不能小于等于 0 page = Math.max(+page, 1) - 1 // page 前端从 1 开始,后台从 0 开始 limit = Math.max(+limit, 10) // 操作数据库一定要 await ctx.body = await User.find().limit(limit).skip(page * limit).select(selectFields) }
  • 如果列表过多,我们需要使用分页查找 mongoodb 提供了 limit skip 字段
  • 列表使用模糊搜索,一个正则搞定cosnt { q = '' } = ctx.query await User.find({ name: new RegExp(q) // 模糊搜索 })如果多个字段搜索呢?await User.find({ $or: [{title: q}, {name: q}] })
  • 使用引用关联表 做个关注用户功能,用户模块添加字段// 获取列表会自动返回following字段 following: { type: [ { type: Schema.Types.ObjectId, // 使用 _id 关联 ref: 'User' // 引用到 User 表 } ] }关注控制器// 关注 async follow(ctx) { // 获取自己(正常需要登录的哈, 从 ctx.state.user._id 获取) const ownUser = await User.findById(ctx.params.my_id) // mongoose 自带的数据类型, 使用toString()方法 if (!ownUser.following.map(id => id.toString()).includes(ctx.params.id)) { ownUser.following.push(ctx.params.id) ownUser.save() } ctx.status = 204 }使用put方法注册路由router.put('/following/:my_id/:id', follow)使用 postman 请求后拉取列表

如果想获取关注者的详细信息使用 populate 关键字:

ctx.body = await User.find({
  name: new RegExp(q) // 模糊搜索
}).limit(limit).skip(page * limit).select(selectFields).populate('following')

之后想写下实战小例子,小程序或者 pc(vue3) 的配合 Koa,但是没想好做什么,感兴趣的朋友可以公众号后台留言呦。

如果文章对你有帮助,欢迎分享到朋友圈!谢谢阅读!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Koa与常用中间件的使用

    Node.js 是一个异步的世界,官方 API 支持的都是 callback 形式的异步编程模型,这会带来许多问题,例如callback 的嵌套问题 ,以及异步...

    越陌度阡
  • 从项目中由浅入深的学习koa 、mongodb(4)

    从项目中由浅入深的学习vue,微信小程序和快应用 (1) 从项目中由浅入深的学习react (2) 从项目中由浅入深的学习typescript (3)

    火狼1
  • 关于koa2,你不知道的事

    koa 是一个基于 node 实现的一个新的 web 框架,它是由 express 框架的原班人马打造。特点是优雅、简洁、表达力强、自由度高。和 express...

    lucifer210
  • Koa封装MySQL数据库

    越陌度阡
  • 分享 koa + mysql 的开发流程,构建 node server端,一次搭建个人博客

    由于一直在用 vue 写业务,为了熟悉下 react 开发模式,所以选择了 react。数据库一开始用的是 mongodb,后来换成 mysql 了,一套下来感...

    大当家
  • Nuxt + Koa2 + Mongodb 手撸一个网上商城

    文档地址:https://finget.github.io/2019/08/06/nuxt-koa-mongodb/

    FinGet
  • Nuxt + Koa2 + Mongodb 手撸一个网上商城

    https://www.runoob.com/mongodb/mongodb-osx-install.html

    FinGet
  • 如何在云托管中操作云开发数据库?

    作为新一代云原生应用引擎(App Engine 2.0),云托管拥有无痛迁移、自动化弹性扩缩容、免运维、支持跨平台部署和联动云开发能力等优势,让开发者可以不限语...

    腾讯云开发TCB
  • iKcamp新书上市《Koa与Node.js开发实战》

    Node.js 10已经进入LTS时代!其应用场景已经从脚手架、辅助前端开发(如SSR、PWA等)扩展到API中间层、代理层及专业的后端开发。Node.js在企...

    iKcamp
  • iKcamp新书上市《Koa与Node.js开发实战》

    Node.js 10已经进入LTS时代!其应用场景已经从脚手架、辅助前端开发(如SSR、PWA等)扩展到API中间层、代理层及专业的后端开发。Node.js在企...

    iKcamp
  • 学习 koa 源码的整体架构,浅析koa洋葱模型原理和co原理

    感兴趣的读者可以点击阅读。 其他源码计划中的有:express、vue-rotuer、redux、 react-redux 等源码,不知何时能写完(哭泣),欢...

    若川
  • RestQL:现代化的 API 开发方式

    koa-restql 已经在 github 开源并在 npm 发布。感兴趣的同学可以前往围观一下。欢迎 Pull Request,同时热烈欢迎 Star。 在现...

    美团技术团队
  • 一杯茶的时间,上手 Koa2 + MySQL 开发

    凭借精巧的“洋葱模型”和对 Promise 以及 async/await 异步编程的完全支持,Koa 框架自从诞生以来就吸引了无数 Node 爱好者。然而 Ko...

    一只图雀
  • node.js之koa2知识点总结

    YungFan
  • koa源码阅读[1]-koa与koa-compose

    接上次挖的坑,对koa2.x相关的源码进行分析 第一篇。 不得不说,koa是一个很轻量、很优雅的http框架,尤其是在2.x以后移除了co的引入,使其代码变得更...

    贾顺名
  • Node.js 基础入门

    Node.js 是一个基于 Chrome V8 引擎 的 JavaScript 运行时环境

    王秀龙
  • nodejs微信公众号开发

    网上关于node开发公众号的资料相当缺乏,本文旨在以node的视角对公众号开发做一个阐述。

    一粒小麦
  • 大家为啥总是在说React比Vue更实用呢?

    React与Vue作为当下最流行的框架有很多相似之处:同样是基于组件的轻量级框架,同样专注于用户界面的视图层。同样可以用在简单的项目中,也同样可以使用全家桶扩展...

    前端达人
  • Koa入门(三)Koa 路由

    在 Koa 应用中,通常会使用 koa-router 模块,提供对路由的支持。那为什么需要路由呢?做前后端分离开发的朋友都遇到过,对接接口的时候后台都会提供一个...

    测不准

扫码关注云+社区

领取腾讯云代金券