Life is Really Short, Have Your Life!!

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

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

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

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

1. 独自スキーマ定義はいらない

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

自分だけかもしれませんが、ORMのスキーマに細かいリレーションシップの定義は不要です。 ActiveRecordhasMany的な定義を事前に入れるのはだるいし、JOIN条件はクエリの内部に書きたい。

自分が求めるのはコンパイルできるSQL(このカラムねぇよ、そんなJOINできませんよ)であって、それ以上の機能は不要。

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

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

業務系システムやWebサービスの管理画面系になると、GroupByを使わない日は無いと思います。Prismaの独自DSLによって、GroupByの条件を指定するのがとてもだるいです。また、GroupByした時、JOINできないのも勘弁してほしかった。CTEとかもどこまでサポートしているか怪しい。

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

これはPrismaが意図的にやっていることであって、あう・あわないはあると思います。よく使うのが、MySQLだと date_format関数などで、それが使えないのは困った。また、includeした場合のクエリの挙動も独特で、それも合わなかった。ORMだから、ある程度発行できるSQLに制御できない部分があるとは思うけど、ちょっとなっていう。

SQLを意識せずDBから値を取ってこれるメリットを何も感じないんですよね。僕はSQLバチバチに意識したい。クエリビルダ型じゃないといやってことに気づきましたw

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

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

というわけで Drizzleに手を出したんですけど、何回やっても、MySQLのautoIncrementを設定したテーブルにINSERTできなくて... Issue上げたけどまったく無視されており、どうしていいかわからん。Issueの数がすごく多くて、怖くて使えたもんじゃない。

github.com

そうなると、残るクエリビルダ型が、KYSELYになる。これが最も自分の好みに近い。良い意味で安定していそう。

kysely.dev

TypeScriptのORMを探すたびは続く。