laravel 13 中用 postgresql 做向量检索需三步:一、确保 pgvector 扩展已启用(create extension if not exists vector);二、迁移中用 raw sql 添加 vector 列,模型中 $casts = ['embedding' => 'string'];三、用 db::select() 或 whereraw() 调用 ? 运算符查询,并建 hnsw 索引提升性能。

直接在 Laravel 13 中用 PostgreSQL 做向量检索,核心是让 pgvector 扩展可用、Eloquent 能安全操作 vector 列、SQL 查询能正确调用距离运算符。Laravel 本身不内置向量支持,但完全兼容 PostgreSQL 的原生能力,关键在于配置和写法适配。
确保 PostgreSQL + pgvector 环境就绪
pgvector 必须已安装并启用,这是前提。不能跳过这步直接写 Laravel 代码。
- 确认 PostgreSQL 版本 ≥ 13(Laravel 13 推荐搭配 PG 15 或 16)
- 在目标数据库中执行:CREATE EXTENSION IF NOT EXISTS vector;
- 验证是否生效:SELECT * FROM pg_extension WHERE extname = 'vector'; 返回一行即成功
- 若用 Docker,推荐镜像如 ankane/pgvector:pg16,避免本地编译踩坑
模型定义与迁移:声明 vector 字段
Laravel 迁移不识别 vector 类型,需用 raw 方式创建列;模型中要禁用自动类型转换,防止 JSON 化或截断。
- 迁移文件中用
DB::unprepared()或原生 SQL 创建列:
DB::unprepared('ALTER TABLE documents ADD COLUMN embedding vector(1536)'); - 模型中添加
$casts避免误处理:
protected $casts = ['embedding' => 'string'];(存为 JSON 字符串格式,如"[0.12, -0.45, ...]") - 插入时传入数组或 JSON 字符串均可,PostgreSQL 会自动转为 vector 类型:
Document::create(['content' => 'xxx', 'embedding' => [0.12, -0.45, 0.88]]);
执行向量相似度查询:绕过 Eloquent 构建器限制
Eloquent 不支持 、 这类自定义运算符,必须用 DB::select() 或 whereRaw() 写原生 SQL。
- 基础语义搜索(最近邻):
DB::select("SELECT id, content, embedding ? AS distance FROM documents ORDER BY embedding ? LIMIT 5", [$queryVector, $queryVector]); - 带业务条件的混合查询(例如只查“已发布”文档):
DB::table('documents')->select('id', 'content', DB::raw('embedding ? AS distance', [$queryVector]))->where('status', 'published')->orderByRaw('embedding ?', [$queryVector])->limit(5)->get(); - 注意:所有向量值需以 PHP 数组形式传入,Laravel 会自动 JSON 编码后交给 PostgreSQL,pgvector 可正确解析
索引与性能关键点
没索引时,百万级向量查询会变全表扫描,响应从毫秒升至秒级。必须手动建 HNSW 或 IVFFlat 索引。
- HNSW 更适合中小项目(精度高、查询快):
DB::unprepared('CREATE INDEX idx_documents_embedding ON documents USING hnsw (embedding vector_l2_ops) WITH (m = 16, ef_construction = 64)'); - 建索引前确保
shared_buffers≥ 512MB,work_mem≥ 64MB(通过postgresql.conf或连接时SET) - 首次建索引较慢,建议在低峰期执行;后续增量写入不影响索引可用性











