MySQL 驱动直连,JdbcClient 直接用:向量混合搜索,一个库全搞定

MySQL 驱动直连,JdbcClient 直接用:向量混合搜索,一个库全搞定

OceanBase 团队最近开源了 seekdb

一句话:它是 AI 原生的混合搜索数据库。在一个库里同时搞定关系型存储(MySQL 100% 兼容)、向量检索(HNSW 索引)、全文搜索、JSON 半结构化数据。

一条 SQL,完成”向量搜索 + 全文匹配 + 结构化过滤”的联合查询。不用写胶水代码拼接技术栈,直接驱动 RAG 流程。

seekdb vs 其他向量数据库

看看 seekdb 和主流方案的对比:

功能 seekdb Chroma Milvus PostgreSQL
嵌入式数据库
MySQL 兼容
向量搜索 插件
全文搜索 部分支持 插件
混合搜索 部分支持
OLTP
OLAP
开源协议 Apache 2.0 Apache 2.0 Apache 2.0 PostgreSQL License

我觉得它最大的几个卖点:

特性 说明
MySQL 兼容 零学习成本,现有客户端直接连
轻量部署 单节点轻量,Docker 就能跑
混合搜索 向量+全文+结构化,一条 SQL 语句搞定
支持嵌入应用 以轻量级库的形式嵌入您的应用

一行命令跑起来

部署有多简单?

1
docker run -d --name seekdb -p 2881:2881 oceanbase/seekdb:latest

完事。用 MySQL 客户端连 localhost:2881 就行。

Python 用户想要嵌入式方式,pip 一装:

1
pip install pyseekdb

Spring Boot 3 + JdbcClient 实战

看代码。

我用 Spring Boot 3.5 + JdbcClient 对接 seekdb,演示三个场景:建表、向量插入、混合搜索。

1. 依赖配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- seekdb 兼容 MySQL 协议 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- LangChain4j 生成 Embedding -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>1.0.0-beta3</version>
</dependency>
</dependencies>

2. 数据库连接

1
2
3
4
5
6
spring:
datasource:
url: jdbc:mysql://localhost:2881/test?useSSL=false
username: root@test
password:
driver-class-name: com.mysql.cj.jdbc.Driver

seekdb 用的是 MySQL 协议,JDBC URL 和驱动都用 MySQL 的。

3. 建表语句

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 文档表,带向量字段
CREATE TABLE documents (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(512) NOT NULL,
content TEXT,
vector VECTOR(1536), -- 1536维,对应 OpenAI ada-002
metadata JSON,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- HNSW 向量索引
CREATE VECTOR INDEX vec_idx ON documents(vector)
WITH (DISTANCE=COSINE, TYPE=HNSW);

VECTOR(1536) 是 seekdb 的向量类型。建索引用 CREATE VECTOR INDEX,语法很直观。

4. 插入向量数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Service
@RequiredArgsConstructor
public class DocumentService {

private final JdbcClient jdbcClient;
private final EmbeddingModel embeddingModel;

public Long insertDocument(String title, String content, String metadata) {
// 生成 Embedding
float[] vector = embeddingModel.embed(title + " " + content)
.content().vector();
String vectorJson = toJsonArray(vector);

return jdbcClient.sql("""
INSERT INTO documents (title, content, vector, metadata)
VALUES (?, ?, ?, ?)
""")
.params(title, content, vectorJson, metadata)
.update();
}

private String toJsonArray(float[] vector) {
return "[" + Arrays.stream(vector)
.mapToObj(String::valueOf)
.collect(Collectors.joining(",")) + "]";
}
}

向量用 JSON 数组格式传进去,seekdb 自动解析。

5. 向量语义搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public List<SearchResult> semanticSearch(String query, int topK) {
float[] queryVector = embeddingModel.embed(query).content().vector();
String vectorJson = toJsonArray(queryVector);

// APPROXIMATE 走 HNSW 索引,速度快
return jdbcClient.sql("""
SELECT id, title, content,
Cosine_distance(vector, ?) AS distance
FROM documents
ORDER BY Cosine_distance(vector, ?) APPROXIMATE
LIMIT ?
""")
.params(vectorJson, vectorJson, topK)
.query(SearchResult.class)
.list();
}

Cosine_distance() 计算余弦距离,值越小越相似。加 APPROXIMATE 走索引,不加就全表扫描(精确但慢)。

6. 混合搜索

这是 seekdb 的杀手锏。向量语义 + 关键词全文匹配,效果比单一方式好得多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public List<HybridSearchResult> hybridSearch(
String query, int topK,
double keywordWeight, // 关键词权重,建议 0.3
double semanticWeight) { // 语义权重,建议 0.7

float[] queryVector = embeddingModel.embed(query).content().vector();
String vectorJson = toJsonArray(queryVector);
String likePattern = "%" + query + "%";

return jdbcClient.sql("""
SELECT id, title, content,
-- 关键词命中得 1 分
CASE WHEN title LIKE ? OR content LIKE ?
THEN 1.0 ELSE 0.0 END AS keyword_score,
-- 语义相似度(距离转相似度)
(1 - Cosine_distance(vector, ?)) AS semantic_score,
-- 加权综合得分
(CASE WHEN title LIKE ? OR content LIKE ?
THEN 1.0 ELSE 0.0 END) * ? +
(1 - Cosine_distance(vector, ?)) * ? AS final_score
FROM documents
ORDER BY final_score DESC
LIMIT ?
""")
.params(likePattern, likePattern, vectorJson,
likePattern, likePattern, keywordWeight,
vectorJson, semanticWeight, topK)
.query(HybridSearchResult.class)
.list();
}

Spring AI Alibaba 快速集成

SpringAI集成架构

注意:这里只能支持向量相似度搜索,没有实现混合搜索的能力。如果需要混合搜索(语义+关键词),还是得自己写 SQL。

依赖

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-store-oceanbase</artifactId>
<version>1.0.0.2</version>
</dependency>

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY}
vectorstore:
oceanbase:
enabled: true
url: jdbc:oceanbase://localhost:2881/test
username:
password:
tableName: ai_documents
defaultTopK: 5
defaultSimilarityThreshold: 0.7

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RestController
@RequiredArgsConstructor
public class RagController {

private final OceanBaseVectorStore vectorStore;

@PostMapping("/documents")
public String addDocuments() {
List<Document> docs = List.of(
new Document("Spring Boot 3.5 发布了", Map.of("type", "news")),
new Document("seekdb 支持混合搜索", Map.of("type", "tech"))
);
vectorStore.add(docs);
return "OK";
}

@GetMapping("/search")
public List<Document> search(@RequestParam String query) {
return vectorStore.similaritySearch(
SearchRequest.builder().query(query).topK(5).build()
);
}
}

Spring AI 的抽象层帮你搞定 Embedding 生成、向量存储、相似度检索。代码量砍半。

写在最后

AI 应用开发正在从”拼凑式架构”走向”一体化架构”。seekdb 代表的 AI 原生数据库思路,本质是把向量能力下沉到数据库层,而不是在应用层做集成。

对 Java 开发者来说,MySQL 兼容意味着几乎零学习成本。JdbcTemplate、JdbcClient、MyBatis 都能直接用。再配合 Spring AI Alibaba 的 VectorStore 抽象,RAG 应用的数据层开发体验提升了一个档次。

如果你正在做 AI 相关的项目,试试 seekdb。