使用 Drizzle ORM 连接 Neon Postgres
Neon 是一款完全托管的无服务器 Postgres。Neon 将计算与存储分离,从而提供自动扩缩、分支和无限存储等功能。你可以通过 @neondatabase/serverless 驱动直接在 Bun 中使用 Neon,也可以通过 Drizzle 这样的 ORM 使用 Neon。
Drizzle ORM 同时支持类似 SQL 的“查询构建器”API 和类似 ORM 的 Queries API。首先创建一个项目目录,使用 bun init 初始化,然后安装 Drizzle 和 Neon 无服务器驱动。
mkdir bun-drizzle-neon
cd bun-drizzle-neon
bun init -y
bun add drizzle-orm @neondatabase/serverless
bun add -D drizzle-kit
创建一个 .env.local 文件,并将你的 Neon Postgres 连接字符串 添加到其中。
DATABASE_URL=postgresql://username:password@ep-adj-noun-guid.us-east-1.aws.neon.tech/neondb?sslmode=require
在 db.ts 中,使用 Neon 无服务器驱动连接到 Neon 数据库,并将其包装在 Drizzle 数据库实例中。
import { neon } from "@neondatabase/serverless";
import { drizzle } from "drizzle-orm/neon-http";
// Bun 会自动从 .env.local 加载 DATABASE_URL
// 参考:https://bun.sh/docs/runtime/environment-variables 获取更多信息
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle({ client: sql });
为了演示数据库的使用,在 index.ts 中添加以下代码。
import { db } from "./db";
import { sql } from "drizzle-orm";
const query = sql`select 'hello world' as text`;
const result = await db.execute(query);
console.log(result.rows);
然后使用 Bun 运行 index.ts。
bun run index.ts
[
{
text: "hello world",
}
]
使用 Drizzle ORM 的基础组件为数据库定义架构。创建一个 schema.ts 文件,并添加以下代码。
import { pgTable, integer, serial, text, timestamp } from "drizzle-orm/pg-core";
export const authors = pgTable("authors", {
id: serial("id").primaryKey(),
name: text("name").notNull(),
bio: text("bio"),
createdAt: timestamp("created_at").notNull().defaultNow(),
});
然后使用 drizzle-kit CLI 生成初始 SQL 迁移。
bunx drizzle-kit generate --dialect postgresql --schema ./schema.ts --out ./drizzle
该命令会创建一个 drizzle 目录,其中包含一个 .sql 迁移文件和一个 meta 目录。
drizzle
├── 0000_aspiring_post.sql
└── meta
├── 0000_snapshot.json
└── _journal.json
使用 migrate.ts 脚本执行这些迁移。该脚本会打开与 Neon 数据库的新连接,并执行 drizzle 目录中所有尚未执行的迁移。
import { db } from "./db";
import { migrate } from "drizzle-orm/neon-http/migrator";
const main = async () => {
try {
await migrate(db, { migrationsFolder: "drizzle" });
console.log("Migration completed");
} catch (error) {
console.error("Error during migration:", error);
process.exit(1);
}
};
main();
使用 bun 运行该脚本。
bun run migrate.ts
Migration completed
现在向数据库中添加一些数据。创建一个 seed.ts 文件,并添加以下内容。
import { db } from "./db";
import * as schema from "./schema";
async function seed() {
await db.insert(schema.authors).values([
{
name: "J.R.R. Tolkien",
bio: "The creator of Middle-earth and author of The Lord of the Rings.",
},
{
name: "George R.R. Martin",
bio: "The author of the epic fantasy series A Song of Ice and Fire.",
},
{
name: "J.K. Rowling",
bio: "The creator of the Harry Potter series.",
},
]);
}
async function main() {
try {
await seed();
console.log("Seeding completed");
} catch (error) {
console.error("Error during seeding:", error);
process.exit(1);
}
}
main();
然后运行此文件。
bun run seed.ts
Seeding completed
数据库现在已经拥有架构和示例数据。将 index.ts 的内容替换为以下代码,即可使用 Drizzle 查询数据库。
import * as schema from "./schema";
import { db } from "./db";
const result = await db.select().from(schema.authors);
console.log(result);
然后运行该文件。它会打印出你插入的三位作者。
bun run index.ts
[
{
id: 1,
name: "J.R.R. Tolkien",
bio: "The creator of Middle-earth and author of The Lord of the Rings.",
createdAt: 2024-05-11T10:28:46.029Z,
}, {
id: 2,
name: "George R.R. Martin",
bio: "The author of the epic fantasy series A Song of Ice and Fire.",
createdAt: 2024-05-11T10:28:46.029Z,
}, {
id: 3,
name: "J.K. Rowling",
bio: "The creator of the Harry Potter series.",
createdAt: 2024-05-11T10:28:46.029Z,
}
]
此示例使用了 Neon 无服务器驱动的 SQL-over-HTTP 功能。Neon 的无服务器驱动还提供了 Client 和 Pool 构造函数,以支持会话、交互式事务和 node-postgres 兼容性。请参阅 Neon 的文档 了解完整概览。
请参阅 Drizzle 网站 获取完整文档。