Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

TypeScriptで好みのORMが見つからない問題

TypeScriptでバックエンドを書いちゃう皆様、ORMは何をお使いですか?

私はシェアが大きい Prismaを使ってみたんですが、どうも肌に合いません。その理由は以下のようなものです。

2025.01.07 追記

まったく同じ理由で自分と同じ構成にしている方がいましたので、こちらどうぞ! Prisimaやめたポイントが同じ!

zenn.dev

1. Prisimaの独自スキーマ、いらない

ORMの特徴として、テーブルのスキーマに合わせてカラムの型、ENUM、外部キー、ユニーク制約などを生成してくれます。Prismaはこれを独自のDSLで実現し、npx prisma generateスキーマを生成します。

自分だけかもしれませんが、ORMのスキーマに細かいリレーションシップの定義は不要です。ActiveRecordhasMany的な定義を事前に入れるのはだるいし、JOIN条件はクエリで組み立てればいいじゃん派。JOIN条件が複合条件になる場合もあるし。enumは欲しいけどね。

そんなに難しくないDSLですけど、DSLを元にコードを自動生成する設計の場合、結局DSLの中身を理解して、クエリを組み立てないといけない。PrismaのWhere句に相当するクエリの書き方は、個人的に肌に合わなかった。覚えるのがだるい。

Prismaのようなスキーマ生成をする場合、その作業をnode.jsのコンテナに入れないといけない。その場合、GAEの無料インスタンスに乗らないんですね。それも個人的な都合でネックでした。無料で充分まわるんだもん、業務系のシステムってユーザー数が少ないからw CloudFlareとかに乗せる時も気になってます。今はもう気にしなくて良さそうだけど。

2. Prisma、集約系の機能が弱い

業務系システムやWebサービスの管理画面系になると、GroupByを使わない日は無いと思います。Prismaの独自DSLによって、GroupByの条件を指定するのがとてもだるい。

GroupByした時、JOINできないのも勘弁してほしかった。CTEも怪しい。

TypedSQLがリリースされましたけど、動的な条件組み立てに対応していないので、あまり使い道がない。

3. Prisma、DB独自の関数が利用できない

Prismaが意図的にやっていること。わからんでもない。ブラックボックスになるしね。MySQLだと date_format関数をよく使うので、それが使えないのは困り申した。

Prismaも良いところはあって、クライアントを拡張できること。ページネーション用の関数を生やしたり、RLSに対応したり、クエリを発行する前に where tenant_id = 2みたいなマルチテナントやる時に必須のWHEREを付け加えたり、クエリ発行後にログを出したりイベント発行したりできる。ミドルウェア的な機能が欲しい場合、現状Prisma一択だと思う。

今の自分は、それが必要じゃなかった。

Drizzle with Kysely

自分がメインで使っているのは、Drizzleです。独自スキーマも要らない(全部TypeScriptになる)し、ORM的な使い方もクエリビルダ的な使い方もできる。Prismaのように、1回のクエリ発行でしれっと2発のSQLを投げるみたいなことがない。JOINした時に、user.post.titleみたいな感じで補完されるのすごく便利... マイグレーションもあるし。

Kyselyはすごく好きなクエリビルダなんだけど、SQLの結果セットをそのまま取得する。オブジェクトがネストされない。user.postにはならず、result.title として取得する必要がある。そのため、SELECT句でカラムを指定することが多くて、集約系のQueryじゃない場合は面倒さがある。

でも、SQLの表現力を最大限活かせるのがKyselyのメリットなので、以下のようなQueryを発行したい場合は、drizzleのスキーマからKyselyのスキーマを吐き出して、Kyselyでクエリを書くのがいいなと思っています。

  • CASE/WHENのようなSELECT句で加工するようなクエリを書きたい
  • DB関数を使いたい
  • GroupBy / Havingなどをガッツリ書きたい
  • CTEを使いたい

上記のようなケースはあまり無いと思うけど、使いたい時はあります。

DuckDB-wasmとかでローカルにDuckDB入れて、クライアントサイドでダッシュボードの集計をするみたいな時代になっているので、SQLをサーバサイドでゴリゴリマッチョすることは減るのかもしれないけど、Kyselyを使うケースはまだまだ多いでしょう。