drizzle-orm 使用笔记

2024 主流的 ts orm 工具,类型安全,无二进制文件依赖,支持各种 serverless 运行时和数据库服务。

初始化

根据环境安装、初始化、编写配置文件等。

比如使用 neon ,可参照:

https://orm.drizzle.team/docs/tutorials/drizzle-with-neon

npm i drizzle-orm @neondatabase/serverless
npm i -D drizzle-kit dotenv

编辑配置文件:

import { config } from 'dotenv';
import { defineConfig } from "drizzle-kit";
config({ path: '.env.local' });
export default defineConfig({
  schema: "./src/schema.ts",
  out: "./migrations",
  dialect: "postgresql",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});

项目中导出客户端:

import { neon } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-http';
import * as schema from './schema';
export const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle({ client: sql, schema });

schema

根据文档 Manage schema 的部分进行设置。

定义表:

import { integer, pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';
export const usersTable = pgTable('users_table', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  age: integer('age').notNull(),
  email: text('email').notNull().unique(),
});

export const postsTable = pgTable('posts_table', {
  id: serial('id').primaryKey(),
  title: text('title').notNull(),
  content: text('content').notNull(),
  userId: integer('user_id')
    .notNull()
    .references(() => usersTable.id, { onDelete: 'cascade' }),
  createdAt: timestamp('created_at').notNull().defaultNow(),
  updatedAt: timestamp('updated_at')
    .notNull()
    .$onUpdate(() => new Date()),
});

获取对应类型:

  • $inferInsert 插入数据库的类型,比如某些字段允许为空
  • $inferSelect 查询出来的类型,全量字段
export type InsertUser = typeof usersTable.$inferInsert;
export type SelectUser = typeof usersTable.$inferSelect;
export type InsertPost = typeof postsTable.$inferInsert;
export type SelectPost = typeof postsTable.$inferSelect;

generate 与 migrate

通过 drizzle-kit 进行。

https://orm.drizzle.team/docs/kit-overview

先执行 generate ,再执行 migrate

drizzle-kit generate
drizzle-kit migrate

支持指定配置文件,应用于多个环境:

drizzle-kit migrate --config=drizzle-dev.drizzle.config

增删改查

在文档 Access your data 处

  • Select 查
  • Insert 创建
  • Update 更新
  • Delete 删除
  • Filters 查询条件
  • Utils 工具,主要是查数量
  • Joins 关联
  • Magic sql operator 自定义 sql 语句

基础增删改成:

db.insert(usersTable).values(data);
db.select().from(usersTable);
db.select().from(usersTable).where(eq(usersTable.id, id));
db.update(postsTable).set(data).where(eq(postsTable.id, id));
db.delete(usersTable).where(eq(usersTable.id, id));

分页+关联查询+排序:

db.select({
  ...getTableColumns(usersTable),
  postsCount: count(postsTable.id),
})
.from(usersTable)
.leftJoin(postsTable, eq(usersTable.id, postsTable.userId))
.groupBy(usersTable.id)
.orderBy(asc(usersTable.id))
.limit(pageSize)
.offset((page - 1) * pageSize);

查询近24小时文章:

db
.select({
  id: postsTable.id,
  title: postsTable.title,
})
.from(postsTable)
.where(between(postsTable.createdAt, sql`now() - interval '1 day'`, sql`now()`))
.orderBy(asc(postsTable.title), asc(postsTable.id))
.limit(pageSize)
.offset((page - 1) * pageSize);

zod

https://orm.drizzle.team/docs/zod

定义:

import { createInsertSchema, createSelectSchema } from 'drizzle-zod';

// 用于创建的验证
const insertUserSchema = createInsertSchema(users);
// 用于查询的验证
const selectUserSchema = createSelectSchema(users);
// 覆盖某个字段的规则
const insertUserSchema = createInsertSchema(users, {
  role: z.string(),
});
// 拓展某个字段的规则
const insertUserSchema = createInsertSchema(users, {
  id: (schema) => schema.id.positive(),
  email: (schema) => schema.email.email(),
  role: z.string(),
});
// 创建后选择 zod Schema 的某些字段
const requestSchema = insertUserSchema.pick({ name: true, email: true });
// 组合新的字段
const registorySchema = insertUserSchema.pick({ name: true, email: true }).extend({
  password: z.string().min(6).max(32)
})
本文收录于专栏
收集一些好用的前端开源库,主要是 npm 包