Drizzle ORM
Drizzle ORM — это лёгкая TypeScript ORM для Node.js с типобезопасным построителем запросов и DSL для описания схемы.
YDB поддерживает интеграцию с Drizzle ORM через адаптер @ydbjs/drizzle-adapter, который входит в YDB JavaScript/TypeScript SDK. Адаптер предоставляет привычный для Drizzle API и учитывает особенности YDB: первичные ключи, вторичные и векторные индексы, TTL, партиционирование и семейства колонок.
Эта страница — краткий обзор интеграции. Подробное руководство со всеми возможностями (построители запросов, реляционный API, миграции, DDL, векторный поиск) доступно на ydb.js.org.
Требования
- Node.js 20.19 или новее
- Пакеты
drizzle-ormи@ydbjs/drizzle-adapter - Доступный экземпляр YDB
Установка
npm install @ydbjs/drizzle-adapter drizzle-orm
Подключение
Самый простой способ — передать строку подключения в createDrizzle(). Адаптер сам создаст и будет управлять драйвером YDB.
import { createDrizzle } from '@ydbjs/drizzle-adapter'
const db = createDrizzle({
connectionString: process.env['YDB_CONNECTION_STRING']!,
})
Строка подключения имеет вид grpc://localhost:2136/local (или grpcs:// для защищённого соединения), где указываются адрес сервера, порт gRPC и путь к базе данных.
Если приложение уже использует драйвер из @ydbjs/core, его можно обернуть в YdbDriver и переиспользовать общее соединение.
import { Driver } from '@ydbjs/core'
import { YdbDriver, createDrizzle } from '@ydbjs/drizzle-adapter'
const driver = new Driver('grpc://localhost:2136/local')
await driver.ready()
const db = createDrizzle({
client: new YdbDriver(driver),
})
После завершения работы освободите ресурсы, если драйвер был создан адаптером:
db.$client.close?.()
Описание схемы
Таблицы описываются с помощью ydbTable(). Для каждой таблицы обязателен первичный ключ.
import { integer, text, timestamp, ydbTable } from '@ydbjs/drizzle-adapter/schema'
export const users = ydbTable('users', {
id: integer('id').primaryKey(),
email: text('email').notNull().unique(),
name: text('name'),
createdAt: timestamp('created_at')
.notNull()
.$defaultFn(() => new Date()),
})
Адаптер поддерживает все основные типы данных YDB (Bool, целочисленные и вещественные типы, Utf8, String, Uuid, Json, типы даты и времени и др.), а также YDB-специфичные возможности схемы: вторичные и векторные индексы, TTL, партиционирование и семейства колонок. Полный перечень типов и опций приведён в руководстве по схеме.
CRUD-операции
import { and, eq, like } from 'drizzle-orm'
// Вставка
await db.insert(users).values({ id: 1, email: 'alice@example.com', name: 'Alice' }).execute()
// Выборка с фильтрацией
const filteredUsers = await db
.select({ userId: users.id, userName: users.name })
.from(users)
.where(and(eq(users.id, 1), like(users.email, '%@example.com')))
.execute()
// Обновление
await db.update(users).set({ name: 'Alice Cooper' }).where(eq(users.id, 1)).execute()
// Удаление
await db.delete(users).where(eq(users.id, 1)).execute()
Для операции «вставить или обновить» по первичному ключу используется onDuplicateKeyUpdate():
await db
.insert(users)
.values({ id: 1, email: 'alice_new@example.com', name: 'Alice Updated' })
.onDuplicateKeyUpdate({ set: { name: 'Alice Updated' } })
.execute()
Транзакции
Транзакции запускаются через db.transaction(). Поддерживаются режимы доступа и уровни изоляции YDB, а также флаг идемпотентности для автоматических повторов при сетевых ошибках.
import { eq } from 'drizzle-orm'
import { TransactionRollbackError } from 'drizzle-orm/errors'
try {
await db.transaction(
async (tx) => {
// Проверяем предусловие перед изменением данных
const inviter = await tx.select().from(users).where(eq(users.id, 1)).execute()
if (inviter.length === 0) {
tx.rollback()
}
await tx.insert(users).values({ id: 4, email: 'delta@example.com' }).execute()
},
{
accessMode: 'read write',
isolationLevel: 'serializableReadWrite',
idempotent: true,
}
)
} catch (error) {
if (error instanceof TransactionRollbackError) {
console.log('transaction was rolled back')
}
}
Ограничения
При использовании адаптера учитывайте особенности YDB и адаптера:
- Адаптер распространяется только в формате ESM.
- Вложенные транзакции не поддерживаются.
- Допустимы только уровни изоляции YDB (
serializableReadWrite,snapshotReadOnly); эмуляции других уровней нет. references()хранится как метаданные для реляционного API — YDB не контролирует внешние ключи на уровне СУБД.