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 не контролирует внешние ключи на уровне СУБД.

Полезные ссылки

Предыдущая
Следующая