我们使用 koa
开发后台,最常用的数据库就是 mongodb
,这是 NoSql
数据库类型的一种,那什么是 NoSql
呢?首先需要说的是,NoSql
并不表示 NO SQL
没有 SQL
的意思。实际上,它是 Not Only SQL
的缩写。它的意义是:适用关系型数据库的时候就使用关系型数据库,不适用的时候也没有必要非使用关系型数据库不可,可以考虑使用更加合适的数据存储。
关系型数据库中的表都是存储一些结构化的数据,每条记录的字段的组成都一样,即使不是每条记录都需要所有的字段,但数据库会为每条数据分配所有的字段。而非关系型数据库以键值对 (key-value)
存储,它的结构不固定,每一条记录可以有不一样的键,每条记录可以根据需要增加一些自己的键值对,这样就不会局限于固定的结构,可以减少一些时间和空间的开销。
MongoDB
使用 C++
语言编写的非关系型数据库。特点是高性能、易部署、易使用,存储数据十分方便。
BSON
(一种 JSON
的扩展)有两种安装方式
一种是使用 mongodb atlas
,官网注册完,直接本地连接就可以了。缺点是需要文明上网,通常连上了也是很慢。注册地址,教程可以参考这里
另一种是安装到本地(我的是windows10,本地快啊),直接安装 msi,启动后直接连接,大家可以自行网上搜索安装。下载地址
npm i mongoose -S
const 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
链接数据库成功
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
测试如下:
增加:
获取列表:
获取某人:
删除某人:
更新用户信息:
我们在操作数据库前一定要判断数据的正确性,例如增加要判断是否已有重名,修改要判断是否有这个用户,一些操作还需要权鉴等等。
koa-parameter
进行参数校验
npm i koa-parameter -S
app/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()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
字段postman
请求后拉取列表如果想获取关注者的详细信息使用 populate
关键字:
ctx.body = await User.find({
name: new RegExp(q) // 模糊搜索
}).limit(limit).skip(page * limit).select(selectFields).populate('following')
之后想写下实战小例子,小程序或者 pc(vue3)
的配合 Koa
,但是没想好做什么,感兴趣的朋友可以公众号后台留言呦。
如果文章对你有帮助,欢迎分享到朋友圈!谢谢阅读!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。