自定义迁移实现Prisma+PostgreSQL全文搜索后遭自动回滚,如何解决
问题描述
Prisma的全文搜索功能仍处于预览阶段,我通过自定义迁移脚本实现PostgreSQL全文搜索,但执行npx prisma migrate dev后,系统自动生成了一个回滚之前修改的新迁移文件,推测是因为Prisma认为schema和迁移脚本不一致。请问如何避免这种情况?
自定义迁移脚本
-- AlterTable ALTER TABLE "Event" ADD COLUMN "searchVector" TSVECTOR GENERATED ALWAYS AS ( setweight(to_tsvector('english', coalesce(title, '')), 'A') || setweight(to_tsvector('english', coalesce(description, '')), 'B') || setweight(to_tsvector('english', coalesce(city, '')), 'C') || setweight(to_tsvector('english', coalesce(state, '')), 'C') || setweight(to_tsvector('english', coalesce(country, '')), 'C') ) STORED; -- CreateIndex CREATE INDEX "Event_searchVector_idx" ON "Event" USING GIN ("searchVector");
Prisma自动生成的回滚脚本
-- DropIndex DROP INDEX "Event_searchVector_idx"; -- AlterTable ALTER TABLE "Event" ALTER COLUMN "searchVector" DROP DEFAULT; -- CreateIndex CREATE INDEX "Event_searchVector_idx" ON "Event"("searchVector");
Event模型定义
model Event { id Int @id @default(autoincrement()) slug String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String description String date DateTime registrationDeadline DateTime price Float? addressLine1 String? addressLine2 String? city String? state String? country String? zipCode String? bannerImgUrl String? eventMode Int language String? searchVector Unsupported("TSVECTOR")? userId Int user User @relation(fields: [userId], references: [id], onDelete: Cascade) speakers EventSpeaker[] comments EventComment[] @@index([searchVector]) }
解决方案
问题根源在于两点:一是Prisma无法识别GENERATED ALWAYS AS (...) STORED的字段定义,二是模型中声明的普通索引和你实际创建的GIN索引不匹配,导致Prisma判定schema与数据库状态不一致,进而生成修正脚本。
按以下步骤解决:
删除模型中的索引声明
把模型里的@@index([searchVector])删掉,让这个GIN索引完全由自定义迁移脚本管理,避免Prisma自动生成普通索引覆盖它。确保必要的PostgreSQL扩展已安装
如果还没安装btree_gin扩展,在自定义迁移脚本开头添加:-- CreateExtension CREATE EXTENSION IF NOT EXISTS btree_gin;这个扩展支持GIN索引的创建,确保索引能正常工作。
标记迁移已成功应用
执行完自定义迁移后,运行命令:npx prisma migrate resolve --applied <你的迁移文件名>告诉Prisma该迁移已经生效,无需再生成修正脚本。
后续变更通过自定义迁移处理
之后涉及searchVector字段或对应索引的修改,都要手动编写自定义迁移脚本,不要依赖Prisma自动生成,避免再次出现冲突。
另外,模型中Unsupported("TSVECTOR")的声明是正确的,因为Prisma不原生支持TSVECTOR类型,这样可以让Prisma忽略该字段的类型校验,仅作为数据库字段的占位符存在。
内容的提问来源于stack exchange,提问作者Sparkzz
相关产品推荐
相关产品推荐

