Supabase, Prisma, pgvectorで画像のSemantic Searchを実現したいので試行錯誤してみる
現在個人開発している画像投稿アプリで画像のあいまい検索を実現したい。
DBはSupabase PostgreSQL、BEはNestjs(TypeScript)とPrismaで構築、画像の特徴ベクトル生成(embedding)はAmazon Bedrockを使用中。
半分備忘録として書き残していきます。
このスクラップで達成したいこと
- pgvectorを使用したPrismaスキーマでDriftを発生させずにマイグレーションを完了させること
- SupabaseのDatabase Functionに登録した特徴ベクトルを使用した検索メソッドを使用して画像のあいまい検索を実現する
すでに達成していること
- postsテーブルに投稿がInsertされたらWebhookを発火し、Amazon Bedrockで画像の特徴ベクトルを生成しpostsテーブルのembeddingフィールドに格納すること
Prismaではpgvectorをまだサポートしていないらしく、無理やり使いたい場合はこんな感じでスキーマ定義する必要があるみたい
schema.prisma
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "linux-arm64-openssl-3.0.x"]
previewFeatures = ["postgresqlExtensions"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_URL")
extensions = [pgvector(map:"vector", schema: "extensions")]
}
model Post {
id String @id @default(uuid())
description String
embedding Unsupported("vector")? //←こんな感じ
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("posts")
}
こちらを参照
このスキーマで
npx prisma migrate dev --create-only
これを実行すると下記のようになって、publicスキーマをリセットさせようとしてくる。
一度だけこれをYesにしてみたことがあるが、各種権限回りもリセットしちゃうみたいで、SupabaseのDatabase Functionに登録した関数を実行しようとすると"public"スキーマへのアクセスが拒否されましたというエラーが発生するようになってしまうので、リセットしない方法を見つけたい。
あとDB全部消えるから毎回これ発生してたらサービスが成立しない。
Drift detected: Your database schema is not in sync with your migration history.
The following is a summary of the differences between the expected database schema given your migrations files, and the actual schema of the database.
It should be understood as the set of changes to get from the expected schema to the actual schema.
If you are running this the first time on an existing database, please make sure to read this documentation page:
https://www.prisma.io/docs/guides/database/developing-with-prisma-migrate/troubleshooting-development
[+] Added extensions
- pgcrypto
[+] Added extensions
- pgsodium
[+] Added extensions
- supabase_vault
[+] Added extensions
- vector
? We need to reset the "public" schema
Do you want to continue? All data will be lost. › (y/N)
Prismaのドキュメント見ると対応してるPostgresのExtensionsが限られてるのかな。
current allowlistでは「citext」「pgcrypto」「uuid-ossp」「postgis」しか書かれてないから、pgvectorは対象外?
schema.prismaにこいつを追記した上でnpx prisma migrate devするとDriftが発生する
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "linux-arm64-openssl-3.0.x"]
previewFeatures = ["postgresqlExtensions"] // ←こいつ
}
記述しなければ発生しない
今日時点でこのIssueに対してPrismaが対応しそうな雰囲気がなさそう。
潔くPrismaを捨てるしかないのか?
pgvector-nodeというライブラリのREADMEには
Note: prisma migrate dev does not support pgvector indexes
と書いてある。じゃあどうすればいいんや。笑
npx prisma db push
このコマンドだったらエラーなど起きずにスキーマの変更をDBに反映できるが、Prismaとしてはdb pushは初期開発フェーズのみ使用し、基本はmigrate devを推奨しているらしい。
ここで詰まった方のために解決策追記しておきます!
こちらのIssueから察するに、PrismaのpostgresqlExtensions
とSupabase側であらかじめインストールされている拡張機能の間に整合性がないことが原因の可能性が高いです!
つまり、以下のような状況が発生しています。
- Supabase側が拡張機能を自動的にインストール
- Prismaがマイグレーション時に「不要な拡張を消そうとする or 必要な拡張を入れようとしている」 とみなしている
- 結果として、毎回
[-] Removed extensions ... [ + ] Added extensions ...
の Drift が発生
よって、取りうる解決策は以下の2パターンあります。
- Prisma側で拡張機能を管理しない
- Supabaseに入っている拡張をすべてPrisma 側にも明示して、差分が出ないようにする
多くの場合は要件上2の方法を取らざるを得ないと思います。その場合は prisma migrate dev --create-only
でマイグレーションファイルを作成し、以下のような形で手動で列挙していく形になると思われます!
CREATE SCHEMA IF NOT EXISTS extensions;
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
CREATE SCHEMA IF NOT EXISTS pgsodium;
CREATE EXTENSION IF NOT EXISTS "pgsodium" WITH SCHEMA "pgsodium";
CREATE EXTENSION IF NOT EXISTS "postgis" WITH VERSION "3.3.2";
CREATE EXTENSION IF NOT EXISTS "postgis" WITH SCHEMA "extensions";
この場合の運用上の懸念点として、Supabaseが将来的に拡張バージョンやインストール状況を変えた際に再び drift が発生する可能性があります。その場合、恐らく適宜新しいバージョンの拡張を入れるマイグレーションを走らせる、という運用になりそうです!