Prisma以外の選択肢、Drizzle ORMではじめるTypeScriptの快適SQLライフ

2023/04/07に公開
2

エッジ環境で使えるORMを探していたところ、Drizzle ORMという新しいORMを知り、感動したので紹介します。
Drizzle ORMはTypeScript向けの強力で柔軟なRDB用のORMです。

https://github.com/drizzle-team/drizzle-orm

Drizzle ORMの主な特徴

強力な型付け

TypeScriptのORMなので当たり前ではありますが、強力な型付けによって型安全に開発することができます。
また、スキーマの定義を以下のようにTypeScriptで行うため、Prismaのようにスキーマを定義したあとにクライアントを生成するといったことは必要はありません。

export const popularityEnum = pgEnum('popularity', [
  'unknown',
  'known',
  'popular',
]);

export const countries = pgTable(
  'countries',
  {
    id: serial('id').primaryKey(),
    name: varchar('name', { length: 256 }),
  },
  (countries) => {
    return {
      nameIndex: uniqueIndex('name_idx').on(countries.name),
    };
  }
);

export const cities = pgTable('cities', {
  id: serial('id').primaryKey(),
  name: varchar('name', { length: 256 }),
  countryId: integer('country_id').references(() => countries.id),
  popularity: popularityEnum('popularity'),
});

InsertとSelectの型をそれぞれ取得することもできます。

// Insert
type NewCountry = InferModel<typeof countries, 'insert'>;

// Select
type Country = InferModel<typeof countries>;

SQLと似た構文

Drizzle ORMの主な哲学として、SQLと似た構文で扱えることが掲げられています。
そのため、SQLを知っている人であれば学習コストが低く、すぐに使い始めることができます。

// Insert
await db.insert(countries).values({
  name: 'Japan',
});

// Select
await db.select().from(countries).where(eq(countries.name, 'Japan'));

柔軟すぎるSelect

Selectでは取得するカラムを指定するだけではなく、返されるオブジェクトの構造を自由に定義することができます。
極端な例ですが、こんなことも可能です。

const result = await db
  .select({
    meta: {
      id: cities.id,
    },
    name: cities.name,
    popularity: cities.popularity,
  })
  .from(cities);

これは、Joinを使うときに威力を発揮します。

const result = await db
  .select({
    city: cities,
    country: countries,
  })
  .from(cities)
  .leftJoin(countries, eq(cities.countryId, countries.id));

この場合resultの型は以下のようになります。

{
  city: {
    id: number;
    name: string;
    countryId: number;
    popularity: "unknown" | "known" | "popular";
  };
  coutry: {
    id: number;
    name: string;
  };
}[]

このように、リレーションをネストしていくことが可能です。

様々なドライバに対応

様々なドライバに対応しており、特にPlanetScaleとNeonのサーバーレスドライバが使えることは大きな利点です。
Cloudflare WorkersなどのHTTPしか使えないエッジ環境でも、データベースにアクセスすることができるためです。

Prismaの場合、Data Proxyを使う必要があるので、余計なコストがかかります。

データベースからスキーマの自動生成が可能

マイグレーションファイルの生成に使うDrizzle KitというCLIツールでは、以下のコマンドで既存のデータベースからTypeScriptのスキーマを自動生成することが可能です。

drizzle-kit introspect:pg --out=migrations/ --connectionString=postgresql://user:pass@host:port/db_name

これによって、現在違うORMで運用中のデータベースでもDrizzle ORMへの移行が少しは楽になると思います。

Zodのスキーマ生成が可能

テーブルのスキーマから型を取得したときと同じように、Zodのスキーマを生成することも可能です。

// Insert
const insertCountrySchema = createInsertSchema(countries);

// Select
const selectCountrySchema = createSelectSchema(countries);

これによって、APIのバリデーションを簡単に実装することが可能になります。
また、次のようにして、スキーマのフィールドを変更したり追加したりできます。

const insertCountrySchema = createInsertSchema(countries, {
  id: (schema) => schema.id.positive(),
  region: z.string(),
});

まとめ

簡単な紹介でしたが、Drizzle ORMのすごさの一端は伝わったのではないかと思います。

とても活発に開発されているので、ロードマップでも眺めながら、Drizzle ORMの採用を考えてみてはどうでしょうか?

https://github.com/orgs/drizzle-team/projects/1

Discussion