跳至主要内容
版本: 最新版本 (v5.0.x)

数据库

数据库

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' })
// or
fastify.register(require('@fastify/redis'), { url: 'redis://127.0.0.1', /* other redis options */ })

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(`server listening on ${fastify.server.address().port}`)
})

默认情况下,@fastify/redis 在 Fastify 服务器关闭时不会关闭客户端连接。若要启用此行为,请像这样注册客户端

fastify.register(require('@fastify/redis'), {
client: redis,
closeClient: true
})

Mongo

运行 npm i @fastify/mongodb 安装插件

用法

const fastify = require('fastify')()

fastify.register(require('@fastify/mongodb'), {
// force to close the mongodb connection when app stopped
// the default value is false
forceClose: true,

url: 'mongodb://mongo/mydb'
})

fastify.get('/user/:id', async function (req, reply) {
// Or this.mongo.client.db('mydb').collection('users')
const users = this.mongo.db.collection('users')

// if the id is an ObjectId format, you need to create a new 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 脚本目录来更改数据库模式。迁移文件夹中的每个文件都需要遵循以下模式: [version].[action].[optional-description].sql

版本: 必须是递增的数字(例如 001 或时间戳)。

操作: 应为 doundodo 实现该版本,undo 撤消它。可以将其视为其他迁移工具中的 updown

可选描述 描述迁移所做的更改。虽然是可选的,但应将其用于所有迁移,因为它使每个人都能更容易地知道迁移中所做的更改。

在我们的示例中,我们将进行一次创建 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', // Postgres and MS SQL Server only
execQuery: (query) => client.query(query),
});

const result = await postgrator.migrate()

if (result.length === 0) {
console.log(
'No migrations run for schema "public". Already at the latest one.'
)
}

console.log('Migration done.')

process.exitCode = 0
} catch(err) {
console.error(err)
process.exitCode = 1
}

await client.end()
}

migrate()