Spring AI + pgvector:用PostgreSQL实现向量搜索
向量数据库这两年很火,Milvus、Pinecone、Weaviate 各有各的生态。但如果你已经在用 PostgreSQL,pgvector 扩展可以让你零额外运维成本获得向量搜索能力——而且 Spring AI 提供了开箱即用的集成。
环境准备
用 Docker 启动带 pgvector 的 PostgreSQL:
dockerrun-d--namepgvector\
-p5432:5432\
-ePOSTGRES_USER=postgres\
-ePOSTGRES_PASSWORD=postgres\
pgvector/pgvector:pg17
镜像 pgvector/pgvector 已内置 vector 扩展,无需手动 CREATE EXTENSION。Spring AI 会在启动时自动初始化所需的表结构和索引(需显式开启 initialize-schema)。
引入依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
注意:Spring AI 2.0 起 initialize-schema 默认关闭,需要显式开启。这是 1.x 到 2.0 的破坏性变更。
配置文件
spring:
datasource:
url:jdbc:postgresql://localhost:5432/postgres
username:postgres
password:postgres
ai:
openai:
api-key:${OPENAI_API_KEY}
vectorstore:
pgvector:
initialize-schema:true
index-type:HNSW
distance-type:COSINE_DISTANCE
dimensions:1536
关键参数说明:
| 参数 | 含义 | 推荐值 |
|---|---|---|
index-type |
索引算法 | HNSW(查询快,构建慢) |
distance-type |
向量距离算法 | COSINE_DISTANCE(文本场景首选) |
dimensions |
向量维度 | 与 Embedding 模型一致(OpenAI=1536) |
initialize-schema |
自动建表 | true(首次启动后关掉) |
写入向量并搜索
@RestController
publicclass SearchController{
@Autowired
privateVectorStorevectorStore;
// 写入知识库文档
@PostMapping("/ingest")
publicStringingest(@RequestBodyList<String>texts){
List<Document>docs=texts.stream()
.map(text->newDocument(text,Map.of("source","manual")))
.toList();
vectorStore.add(docs);
return" ingested "+docs.size()+" docs";
}
// 语义搜索
@GetMapping("/search")
publicList<String>search(@RequestParamStringq){
returnvectorStore.similaritySearch(
SearchRequest.builder()
.query(q)
.topK(5)
.similarityThreshold(0.7)
.build()
).stream()
.map(Document::getText)
.toList();
}
}
调用 /search?q=Spring Boot如何配置虚拟线程 会返回语义最相关的文档片段,而不是简单的关键词匹配。
元数据过滤
pgvector 支持基于 JSON 路径的元数据过滤,适合多租户、分来源的场景:
vectorStore.similaritySearch(
SearchRequest.builder()
.query("虚拟线程配置")
.topK(3)
.filterExpression("source == 'manual' && year >= 2026")
.build()
);
过滤器会被转换为 PostgreSQL 的 jsonb_path_match 查询,性能开销很低。
踩坑记录
1. dimensions 不匹配
如果 dimensions 配置与 Embedding 模型输出不一致(比如 OpenAI text-embedding-3-small 是 1536,text-embedding-3-large 是 3072),写入时会直接报 SQL 错误。先确认模型的维度数再配置。
2. initialize-schema 只开发环境开
生产环境建议手动执行 DDL,关闭自动建表。手动 SQL:
CREATEEXTENSIONIFNOTEXISTSvector;
CREATETABLEIFNOTEXISTSvector_store(
iduuidDEFAULTuuid_generate_v4()PRIMARYKEY,
contenttext,
metadatajsonb,
embeddingvector(1536)
);
CREATEINDEXONvector_storeUSINGHNSW(embeddingvector_cosine_ops);
3. 不用 pgvector 时关掉扩展
Spring AI 的 starter 会自动加载 PgVectorStore,如果不需要向量搜索,排除 starter 或加上 spring.ai.vectorstore.pgvector.enabled=false,否则启动报连接超时。
小结
如果你已经在用 PostgreSQL,pgvector 是最轻量的向量搜索方案——无需新服务、无需新运维、学习成本几乎为零。配合 Spring AI 的 VectorStore 抽象,未来换 Milvus 或 Pinecone 也只需改一个依赖,代码不用动。
完整示例代码见 Spring AI 官方文档。
参考:Spring AI - PGvector
夜雨聆风