@ 细雨- 适应器/ 节点- 张贴
PostgreSQL 应用节点-postgres (pg)驱动程序对 Drizzle 适配器生态系统实施.
概览
这个 @drizzle-adapter/node-postgres 软件包为 Drizzle 适应器接口提供 PostgreSQL 执行 node-postgres 驾驶员。 虽然你不直接与此软件包互动( 您使用 @drizzle-adapter/core 相反,它使PostgreSQL能够在Drizzle适应器生态系统中提供支持.
为什么是节点派?
节点后置驱动程序具有若干优点:
- 成熟和稳定:多年生产试验
- 本地连接集成: 内置连接池管理
- 完整特性支持: 访问所有 PostgreSQL 特性
- 二进制数据支持: 高效的二进制数据处理
- 发言稿: 自动准备和缓存语句
- 类型解析: PostgreSQL 数据类型的原生处理
- SSL 支持: 安全连接到完整的 SSL 配置
- 主动维护: 定期更新和安全补丁
安装
# Install both the core package and the PostgreSQL adapter
pnpm install @drizzle-adapter/core @drizzle-adapter/node-postgres
重要:适配器注册
适配器要正确使用 DrizzleAdapterFactory 操作,必须导入它进行自我注册的副作用:
// Import for side effects - adapter will self-register
import '@drizzle-adapter/node-postgres';
// Now you can use the factory
import { DrizzleAdapterFactory } from '@drizzle-adapter/core';
使用量
配置
import { DrizzleAdapterFactory, TypeDrizzleDatabaseConfig } from '@drizzle-adapter/core';
const config: TypeDrizzleDatabaseConfig = {
DATABASE_DRIVER: 'node-postgres',
DATABASE_URL: 'postgresql://user:password@localhost:5432/database'
};
const factory = new DrizzleAdapterFactory();
const adapter = factory.create(config);
Schema 定义
const dataTypes = adapter.getDataTypes();
const users = dataTypes.dbTable('users', {
id: dataTypes.dbSerial('id').primaryKey(),
name: dataTypes.dbText('name').notNull(),
email: dataTypes.dbText('email').notNull().unique(),
profile: dataTypes.dbJsonb('profile'),
searchVector: dataTypes.dbTsVector('search_vector'),
createdAt: dataTypes.dbTimestampTz('created_at').defaultNow()
});
const posts = dataTypes.dbTable('posts', {
id: dataTypes.dbSerial('id').primaryKey(),
userId: dataTypes.dbInteger('user_id')
.references(() => users.id),
title: dataTypes.dbText('title').notNull(),
content: dataTypes.dbText('content').notNull(),
tags: dataTypes.dbArray('tags', { type: 'text' }),
metadata: dataTypes.dbJsonb('metadata'),
published: dataTypes.dbBoolean('published').default(false),
createdAt: dataTypes.dbTimestampTz('created_at').defaultNow()
});
基本 CRUD 操作
import { eq, and, or, desc, sql } from 'drizzle-orm';
const connection = await adapter.getConnection();
const client = connection.getClient();
try {
// INSERT
// Single insert with returning
const [newUser] = await client
.insert(users)
.values({
name: 'John Doe',
email: '[email protected]',
profile: { bio: 'Hello!' }
})
.returning();
// Bulk insert
await client
.insert(posts)
.values([
{
userId: newUser.id,
title: 'First Post',
content: 'Hello, world!',
tags: ['hello', 'first']
},
{
userId: newUser.id,
title: 'Second Post',
content: 'Another post',
tags: ['second']
}
]);
// SELECT
// Select all
const allUsers = await client
.select()
.from(users);
// Select with conditions
const user = await client
.select()
.from(users)
.where(eq(users.email, '[email protected]'));
// Select with join and array operations
const postsWithTags = await client
.select({
userName: users.name,
postTitle: posts.title,
tags: posts.tags
})
.from(posts)
.leftJoin(users, eq(posts.userId, users.id))
.where(sql`${posts.tags} && ARRAY['hello']::text[]`)
.orderBy(desc(posts.createdAt));
// Full-text search
const searchResults = await client
.select()
.from(posts)
.where(sql`to_tsvector('english', ${posts.title} || ' ' || ${posts.content}) @@ to_tsquery('english', 'hello')`)
.orderBy(desc(posts.createdAt));
// UPDATE
// Update with JSONB operations
await client
.update(users)
.set({
profile: sql`${users.profile} || '{"title": "New Title"}'::jsonb`
})
.where(eq(users.id, newUser.id));
// DELETE
await client
.delete(posts)
.where(
and(
eq(posts.userId, newUser.id),
eq(posts.published, false)
)
);
} finally {
// Always close the connection
await connection.disconnect();
}
高级特性
交易支持
const connection = await adapter.getConnection();
const client = connection.getClient();
try {
await client.transaction(async (tx) => {
const [user] = await tx
.insert(users)
.values({
name: 'John Doe',
email: '[email protected]'
})
.returning();
await tx
.insert(posts)
.values({
userId: user.id,
title: 'My First Post',
content: 'Hello, world!'
});
});
} finally {
await connection.disconnect();
}
全文搜索
// Create search vector
await client.execute(sql`
UPDATE ${posts}
SET search_vector = to_tsvector('english', title || ' ' || content)
`);
// Create GiST index
await client.execute(sql`
CREATE INDEX posts_search_idx ON ${posts} USING GiST (search_vector)
`);
// Search posts
const results = await client
.select()
.from(posts)
.where(sql`${posts.searchVector} @@ to_tsquery('english', ${searchQuery})`)
.orderBy(sql`ts_rank(${posts.searchVector}, to_tsquery('english', ${searchQuery})) DESC`);
阵列操作
// Find posts with specific tags
const taggedPosts = await client
.select()
.from(posts)
.where(sql`${posts.tags} && ARRAY['typescript', 'postgresql']`);
// Add tag to existing tags
await client
.update(posts)
.set({
tags: sql`array_append(${posts.tags}, 'new-tag')`
})
.where(eq(posts.id, postId));
最佳做法
- 连接管理: 总是尝试/最后使用以确保连接被关闭
- 交易: 相关业务使用交易
- 发言稿: 报表自动编制并缓存
- 处理错误: 执行适当的错误处理和重试
- 查询优化: 使用索引和适当的查询规划
捐款
我们欢迎捐款! 请随意提交拉力请求 对于重大变动,请先开出一个问题来讨论你想要改变什么.
相关软件包
- @ 细雨适应器/ 核心 - 核心接口和类型
- @ 细雨适应器/ pg- core - 共享 PostgreSQL 功能
- @ 细雨适应器/ postgres-js - 替代PostgreSQL适配器