数据库
Fastify 生态系统提供了一系列插件,用于连接各种数据库引擎。本指南涵盖了 Fastify 组织内维护的数据库引擎。
如果您选择的数据库没有对应的插件, 您仍然可以使用该数据库,因为 Fastify 是与数据库无关的。 可以参考本指南中列出的数据库插件示例来编写缺失的数据库引擎插件。
如需编写自己的 Fastify 插件,请参阅 插件指南
MySQL
通过运行 npm i @fastify/mysql
安装该插件。
使用方法:
const fastify = require('fastify')()
fastify.register(require('@fastify/mysql'), {
connectionString: 'mysql://root@localhost/mysql'
})
fastify.get('/user/:id', function(req, reply) {
fastify.mysql.query(
'SELECT id, username, hash, salt FROM users WHERE id=?', [req.params.id],
function onResult (err, result) {
reply.send(err || result)
}
)
})
fastify.listen({ port: 3000 }, err => {
if (err) throw err
console.log(`server listening on ${fastify.server.address().port}`)
})
Postgres
通过运行 npm i pg @fastify/postgres
安装该插件。
示例:
const fastify = require('fastify')()
fastify.register(require('@fastify/postgres'), {
connectionString: 'postgres://postgres@localhost/postgres'
})
fastify.get('/user/:id', function (req, reply) {
fastify.pg.query(
'SELECT id, username, hash, salt FROM users WHERE id=$1', [req.params.id],
function onResult (err, result) {
reply.send(err || result)
}
)
})
fastify.listen({ port: 3000 }, err => {
if (err) throw err
console.log(`server listening on ${fastify.server.address().port}`)
})
Redis
运行 npm i @fastify/redis
安装插件
用法:
'use strict'
const fastify = require('fastify')()
fastify.register(require('@fastify/redis'), { host: '127.0.0.1' })
// 或者
fastify.register(require('@fastify/redis'), { url: 'redis://127.0.0.1', /* 其他 Redis 选项 */ })
fastify.get('/foo', function (req, reply) {
const { redis } = fastify
redis.get(req.query.key, (err, val) => {
reply.send(err || val)
})
})
fastify.post('/foo', function (req, reply) {
const { redis } = fastify
redis.set(req.body.key, req.body.value, (err) => {
reply.send(err || { status: 'ok' })
})
})
fastify.listen({ port: 3000 }, err => {
if (err) throw err
console.log(`服务器监听在 ${fastify.server.address().port}`)
})
默认情况下,@fastify/redis
不会在 Fastify 服务器关闭时关闭客户端连接。
要启用此行为,请像这样注册客户端:
fastify.register(require('@fastify/redis'), {
client: redis,
closeClient: true
})
MongoDB
运行 npm i @fastify/mongodb
安装插件
用法:
const fastify = require('fastify')()
fastify.register(require('@fastify/mongodb'), {
// 强制在应用停止时关闭 MongoDB 连接
// 默认值为 false
forceClose: true,
url: 'mongodb://mongo/mydb'
})
fastify.get('/user/:id', async function (req, reply) {
// 或者使用 this.mongo.client.db('mydb').collection('users')
const users = this.mongo.db.collection('users')
// 如果 id 是 ObjectId 格式,需要创建一个新的 ObjectId
const id = this.mongo.ObjectId(req.params.id)
try {
const user = await users.findOne({ id })
return user
} catch (err) {
return err
}
})
fastify.listen({ port: 3000 }, err => {
if (err) throw err
})
LevelDB
安装插件,请运行 npm i @fastify/leveldb
用法示例:
const fastify = require('fastify')()
fastify.register(
require('@fastify/leveldb'),
{ name: 'db' }
)
fastify.get('/foo', async function (req, reply) {
const val = await this.level.db.get(req.query.key)
return val
})
fastify.post('/foo', async function (req, reply) {
await this.level.db.put(req.body.key, req.body.value)
return { status: 'ok' }
})
fastify.listen({ port: 3000 }, err => {
if (err) throw err
console.log(`server listening on ${fastify.server.address().port}`)
})
编写数据库库插件
我们也可以为一个数据库库编写插件(例如 Knex、Prisma 或 TypeORM)。 我们将使用 Knex 作为示例。
'use strict'
const fp = require('fastify-plugin')
const knex = require('knex')
function knexPlugin(fastify, options, done) {
if(!fastify.knex) {
const knex = knex(options)
fastify.decorate('knex', knex)
fastify.addHook('onClose', (fastify, done) => {
if (fastify.knex === knex) {
fastify.knex.destroy(done)
}
})
}
done()
}
export default fp(knexPlugin, { name: 'fastify-knex-example' })
编写数据库引擎插件
在此示例中,我们将从头开始创建一个基本的 Fastify MySQL 插件(这是一个精简版示例,请在生产环境中使用官方插件)。
const fp = require('fastify-plugin')
const mysql = require('mysql2/promise')
function fastifyMysql(fastify, options, done) {
const connection = mysql.createConnection(options)
if (!fastify.mysql) {
fastify.decorate('mysql', connection)
}
fastify.addHook('onClose', (fastify, done) => connection.end().then(done).catch(done))
done()
}
export default fp(fastifyMysql, { name: 'fastify-mysql-example' })
数据库迁移
数据库模式迁移是数据库管理和开发的重要组成部分。迁移提供了一种可重复和可测试的方式来修改数据库的模式,并防止数据丢失。
如本指南开头所述,Fastify 是与数据库无关的,可以使用任何 Node.js 数据库迁移工具。我们将演示如何使用 Postgrator ,该工具支持 Postgres、MySQL、SQL Server 和 SQLite。对于 MongoDB 迁移,请参阅 migrate-mongo 。
Postgrator
Postgrator 是一个用于 Node.js 的 SQL 迁移工具,它使用目录中的 SQL 脚本来更改数据库模式。迁移文件夹中的每个文件需要遵循以下格式:[版本].[操作].[可选描述].sql
。
版本: 必须是一个递增的数字(例如 001
或时间戳)。
操作: 应该是 do
或 undo
。do
实现版本,undo
反转它。可以将其视为其他迁移工具中的 up
和 down
。
可选描述 描述了迁移所做的更改。虽然它是可选的,但应该为所有迁移使用,因为它使每个人更容易了解迁移中进行了哪些更改。
在我们的示例中,我们将创建一个包含 users
表的单个迁移,并将使用 Postgrator 来运行该迁移。
运行
npm i pg postgrator
安装示例所需的依赖项。
// 001.do.create-users-table.sql
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY NOT NULL,
created_at DATE NOT NULL DEFAULT CURRENT_DATE,
firstName TEXT NOT NULL,
lastName TEXT NOT NULL
);
const pg = require('pg')
const Postgrator = require('postgrator')
const path = require('node:path')
async function migrate() {
const client = new pg.Client({
host: 'localhost',
port: 5432,
database: 'example',
user: 'example',
password: 'example',
});
try {
await client.connect();
const postgrator = new Postgrator({
migrationPattern: path.join(__dirname, '/migrations/*'),
driver: 'pg',
database: 'example',
schemaTable: 'migrations',
currentSchema: 'public', // PostgreSQL 和 MS SQL Server 专用
execQuery: (query) => client.query(query),
});
const result = await postgrator.migrate()
if (result.length === 0) {
console.log(
'没有为模式 "public" 运行迁移。已经是最新的了。'
)
}
const result = await postgrator.migrate()
if (result.length === 0) {
console.log(
'没有对模式 "public" 进行迁移。已经是最新状态了。'
)
}
console.log('迁移完成。')
process.exitCode = 0
} catch(err) {
console.error(err)
process.exitCode = 1
}
await client.end()
}
migrate()