一、前置准备
-
安装 Milvus
- 单机版:
docker-compose up -d(使用官方 Docker 配置) - 集群版:参考官方部署文档
- 单机版:
-
Milvus Java SDK
xmlCopy Code <dependency> <groupId>io.milvus</groupId> <artifactId>milvus-sdk-java</artifactId> <version>2.3.4</version> <!-- 根据版本更新 --> </dependency>
二、SpringBoot 集成步骤
1. 配置连接参数(application.yml)
yamlCopy Code
milvus:
host: 127.0.0.1
port: 19530
collection-name: product_vectors # 自定义集合名称
vector-dim: 512 # 向量维度(需与实际数据匹配)
2. 配置 Milvus 客户端 Bean
javaCopy Code
@Configuration
public class MilvusConfig {
@Value("${milvus.host}")
private String host;
@Value("${milvus.port}")
private int port;
@Bean
public MilvusServiceClient milvusClient() {
ConnectParam connectParam = ConnectParam.newBuilder()
.withHost(host)
.withPort(port)
.build();
return new MilvusServiceClient(connectParam);
}
}
3. 定义向量操作服务类
javaCopy Code
@Service
public class VectorSearchService {
@Autowired
private MilvusServiceClient milvusClient;
@Value("${milvus.collection-name}")
private String collectionName;
@Value("${milvus.vector-dim}")
private Integer vectorDim;
// 创建集合(首次使用)
public void createCollection() {
FieldType fieldId = FieldType.newBuilder()
.withName("id")
.withDataType(DataType.Int64)
.withPrimaryKey(true)
.build();
FieldType fieldVector = FieldType.newBuilder()
.withName("vector")
.withDataType(DataType.FloatVector)
.withDimension(vectorDim)
.build();
CreateCollectionParam createParam = CreateCollectionParam.newBuilder()
.withCollectionName(collectionName)
.addFieldType(fieldId)
.addFieldType(fieldVector)
.build();
milvusClient.createCollection(createParam);
}
// 插入向量数据
public List<Long> insertVectors(List<List<Float>> vectors) {
List<Long> ids = generateIds(vectors.size()); // 生成唯一ID(如雪花算法)
InsertParam insertParam = InsertParam.newBuilder()
.withCollectionName(collectionName)
.addField("id", ids)
.addField("vector", vectors)
.build();
milvusClient.insert(insertParam);
return ids;
}
// 向量相似度搜索(Top-K)
public List<Long> searchSimilarVectors(List<Float> queryVector, int topK) {
List<List<Float>> queryVectors = Collections.singletonList(queryVector);
SearchParam searchParam = SearchParam.newBuilder()
.withCollectionName(collectionName)
.withVectors(queryVectors)
.withTopK(topK)
.withMetricType(MetricType.L2) // 或 COSINE/IP
.build();
SearchResults resp = milvusClient.search(searchParam);
return parseResultIds(resp);
}
}
三、实际用例:商品图片相似推荐
场景描述
- 用户上传一张商品图片 → 提取图片特征向量(如 ResNet-512D) → 在 Milvus 中搜索 Top-5 相似商品
控制器层代码
javaCopy Code
@RestController
@RequestMapping("/api/search")
public class SearchController {
@Autowired
private VectorSearchService vectorService;
@PostMapping("/image")
public ResponseEntity<?> searchByImage(@RequestBody float[] imageFeatures) {
// 转换为List<Float>(Milvus要求格式)
List<Float> queryVector = Arrays.stream(imageFeatures).boxed().collect(Collectors.toList());
List<Long> productIds = vectorService.searchSimilarVectors(queryVector, 5);
return ResponseEntity.ok(productIds);
}
}
四、关键注意事项
-
性能优化
-
插入数据后调用
flush()确保数据持久化 -
创建索引(如
IVF_FLAT或HNSW)加速搜索:javaCopy Code milvusClient.createIndex(CreateIndexParam.newBuilder() .withCollectionName(collectionName) .withFieldName("vector") .withIndexType(IndexType.IVF_FLAT) .withMetricType(MetricType.L2) .build());
-
-
错误处理
- 检查响应状态码:
resp.getStatus() == Status.Success.code - 处理
MilvusException异常
- 检查响应状态码:
-
版本兼容性
- Milvus 2.x 与 1.x API 不兼容,需确认 SDK 版本