@astrojs/ db
Astro DB 是一个为 Astro 生态系统设计的完全托管的 SQL 数据库:在 Astro 中进行本地开发,并部署到任何与 libSQL 兼容的数据库。
使用 Astro DB,你就拥有了一个强大的、本地的、类型安全的工具,可以将内容作为关系数据库来查询和建模。
Astro 包含一个 astro add
命令来自动设置官方集成。如果你愿意,也可以手动安装集成。
在新的终端窗口中运行以下命令之一。
npx astro add db
pnpm astro add db
yarn astro add db
手动安装
标题为“手动安装”的部分如果你更喜欢自己从头开始设置,可以跳过 astro add
命令,并按照以下说明自行安装 Astro DB。
1. 通过包管理器从 npm 安装集成
标题为“1. 通过包管理器从 npm 安装集成”的部分npm install @astrojs/db
pnpm add @astrojs/db
yarn add @astrojs/db
2. 将集成添加到 astro.config.mjs
标题为“2. 将集成添加到 astro.config.mjs”的部分import { defineConfig } from 'astro/config';import db from '@astrojs/db';
export default defineConfig({ integrations: [ db() ]});
3. 配置你的数据库
标题为“3. 配置你的数据库”的部分在你的项目根目录下创建一个 db/config.ts
文件。这是一个特殊文件,Astro 会自动加载并用它来配置你的数据库表。
import { defineDb } from 'astro:db';
export default defineDb({ tables: {},})
表格配置参考
标题为“表格配置参考”的部分columns
标题为“columns”的部分表列是使用 columns
对象来配置的。
import { defineTable, column, NOW } from 'astro:db';
const Comment = defineTable({ columns: { id: column.number({ primaryKey: true }), author: column.text(), content: column.text({ optional: true }), published: column.date({ default: NOW }), },});
列是使用 column
实用工具配置的。column
支持以下类型:
column.text(...)
- 存储纯文本或富文本内容column.number(...)
- 存储整数和浮点数值column.boolean(...)
- 存储 true / false 值column.date(...)
- 存储Date
对象,为数据存储解析为 ISO 字符串column.json(...)
- 存储任意 JSON blob,为数据存储解析为字符串化的 JSON
所有列共享一些配置值:
primaryKey
- 将一个number
或text
类型的列设置为主键。optional
- 默认情况下,Astro DB 对所有列都使用NOT NULL
。将optional
设置为true
以允许空值。default
- 为新插入的条目设置默认值。这接受一个静态值或一个sql
字符串,用于生成像时间戳这样的值。unique
- 将列标记为唯一。这可以防止表中不同条目出现重复值。references
- 按列引用相关表。这将建立一个外键约束,意味着每个列值必须在被引用的表中有匹配的值。
indexes
标题为“indexes”的部分表索引用于提高对给定列或列组合的查找速度。indexes
属性接受一个配置对象数组,用于指定要索引的列:
import { defineTable, column } from 'astro:db';
const Comment = defineTable({ columns: { authorId: column.number(), published: column.date(), body: column.text(), }, indexes: [ { on: ["authorId", "published"], unique: true }, ]});
这将在 authorId
和 published
列上生成一个名为 Comment_authorId_published_idx
的唯一索引。
每个索引都有以下配置选项可用:
on
:string | string[]
- 要索引的单个列或列名数组。unique
:boolean
- 设置为true
以在索引列中强制执行唯一值。name
:string
(可选) - 唯一索引的自定义名称。这将覆盖 Astro 根据被索引的表和列名生成的名称(例如Comment_authorId_published_idx
)。自定义名称是全局的,因此请确保索引名称在表之间不冲突。
foreignKeys
标题为“foreignKeys”的部分foreignKeys
是一个用于关联多个表列的高级 API。如果你只需要引用单个列,请尝试使用列的 references
属性。
外键用于在两个表之间建立关系。foreignKeys
属性接受一个配置对象数组,可以关联表之间的一个或多个列:
import { defineTable, column } from 'astro:db';
const Author = defineTable({ columns: { firstName: column.text(), lastName: column.text(), },});
const Comment = defineTable({ columns: { authorFirstName: column.text(), authorLastName: column.text(), body: column.text(), }, foreignKeys: [ { columns: ["authorFirstName", "authorLastName"], references: () => [Author.columns.firstName, Author.columns.lastName], }, ],});
每个外键配置对象接受以下属性:
columns
:string[]
- 要与引用表关联的列名数组。references
:() => Column[]
- 一个返回被引用表中的列数组的函数。
Astro DB CLI 参考
标题为“Astro DB CLI 参考”的部分Astro DB 包含一组 CLI 命令,用于与你的本地和与 libSQL 兼容的数据库进行交互。
这些命令在使用 GitHub CI action 时会自动调用,也可以使用 astro db
CLI 手动调用。
astro db push
标题为“astro db push”的部分标志
--force-reset
如果需要进行破坏性的 schema 更改,则重置所有生产数据。
安全地将数据库配置更改推送到你的项目数据库。此命令会检查任何数据丢失的风险,并指导你完成任何推荐的迁移步骤。如果必须进行破坏性的 schema 更改,请使用 --force-reset
标志来重置所有生产数据。
astro db verify
标题为“astro db verify”的部分检查你的本地和远程数据库配置之间的任何差异。此命令由 astro db push
自动运行。verify
将比较你的本地 db/config.ts
文件与远程数据库,并在检测到更改时发出警告。
astro db execute <file-path>
标题为“astro db execute <file-path>”的部分标志
--remote
针对与 libSQL 兼容的数据库运行。省略此标志则针对你的开发服务器运行。
执行一个 .ts
或 .js
文件来读写你的数据库。此命令接受一个文件路径作为参数,并支持使用 astro:db
模块来编写类型安全的查询。使用 --remote
标志来针对与 libSQL 兼容的数据库运行,或省略该标志以针对你的开发服务器运行。有关示例文件,请参阅如何为开发填充数据库。
astro db shell --query <sql-string>
标题为“astro db shell --query <sql-string>”的部分标志
--query
要执行的原始 SQL 查询。--remote
针对与 libSQL 兼容的数据库运行。省略此标志则针对你的开发服务器运行。
对你的数据库执行原始 SQL 查询。使用 --remote
标志来针对与 libSQL 兼容的数据库运行,或省略该标志以针对你的开发服务器运行。
Astro DB 实用工具参考
标题为“Astro DB 实用工具参考”的部分isDbError()
标题为“isDbError()”的部分isDbError()
函数检查一个错误是否是 libSQL 数据库异常。这可能包括使用引用时的外键约束错误,或插入数据时缺少字段。你可以将 isDbError()
与 try / catch 块结合使用来处理应用程序中的数据库错误:
import { db, Comment, isDbError } from 'astro:db';import type { APIRoute } from 'astro';
export const POST: APIRoute = (ctx) => { try { await db.insert(Comment).values({ id: ctx.params.id, content: 'Hello, world!' }); } catch (e) { if (isDbError(e)) { return new Response(`Cannot insert comment with id ${id}\n\n${e.message}`, { status: 400 }); } return new Response('An unexpected error occurred', { status: 500 }); }
return new Response(null, { status: 201 });};