向量数据库实战:Milvus入门与Java集成

前言

向量数据库是 RAG 系统的核心组件,负责存储和检索高维向量数据。Milvus 是最流行的开源向量数据库,支持十亿级向量检索。本文带你快速入门 Milvus,并完成 Java 集成。

一、Milvus 核心概念

  • Collection:向量数据的集合,类似数据库中的表
  • Partition:集合的分区,提升查询性能
  • Vector Field:存储向量数据的字段
  • Index:向量索引,决定检索性能
  • Metric Type:相似度度量方式(IP欧式距离 / L2欧式距离)

二、快速部署 Milvus(Docker)

# 下载 docker-compose.yml
wget https://github.com/milvus-io/milvus/releases/download/v2.3.3/milvus-standalone-docker-compose.yml -O docker-compose.yml

# 启动 Milvus
docker-compose up -d

# 验证服务
docker ps | grep milvus

三、Java 客户端配置

<dependency>
    <groupId>io.milvus</groupId>
    <artifactId>milvus-sdk-java</artifactId>
    <version>2.3.4</version>
</dependency>
import io.milvus.client.MilvusClient;
import io.milvus.param.ConnectParam;
import io.milvus.param.collection.FieldType;
import io.milvus.param.collection.CreateCollectionParam;

public class MilvusConfig {
    private static final String HOST = "localhost";
    private static final int PORT = 19530;

    public static MilvusClient createClient() {
        ConnectParam param = ConnectParam.newBuilder()
            .withHost(HOST)
            .withPort(PORT)
            .build();
        return new MilvusClient(param);
    }
}

四、创建 Collection

public void createCollection(MilvusClient client) {
    // 定义字段
    FieldType idField = FieldType.newBuilder()
        .withName("id")
        .withDataType(DataType.Int64)
        .withPrimaryKey(true)
        .build();

    FieldType vectorField = FieldType.newBuilder()
        .withName("embedding")
        .withDataType(DataType.FloatVector)
        .withDimension(1536)  // OpenAI text-embedding-3-small 默认维度
        .build();

    FieldType textField = FieldType.newBuilder()
        .withName("text")
        .withDataType(DataType.VarChar)
        .withMaxLength(65535)
        .build();

    CreateCollectionParam param = CreateCollectionParam.newBuilder()
        .withCollectionName("documents")
        .withDescription("Document embeddings collection")
        .addFieldType(idField)
        .addFieldType(vectorField)
        .addFieldType(textField)
        .build();

    client.createCollection(param);
    System.out.println("Collection created: documents");
}

五、插入向量数据

public void insertVectors(MilvusClient client, List<Float[]> vectors, List<String> texts) {
    List<List<Float>> vectorList = vectors.stream()
        .map(v -> Arrays.asList(v))
        .collect(Collectors.toList());

    List<InsertParam.Field> fields = Arrays.asList(
        new InsertParam.Field("id", Arrays.asList(1L, 2L, 3L)),
        new InsertParam.Field("embedding", vectorList),
        new InsertParam.Field("text", texts)
    );

    InsertParam param = InsertParam.newBuilder()
        .withCollectionName("documents")
        .withFields(fields)
        .build();

    MutationResult result = client.insert(param);
    System.out.println("Inserted " + result.getSuccIndexCount() + " vectors");

    // 加载Collection到内存
    client.loadCollection("documents");
}

六、向量检索

public void search(MilvusClient client, float[] queryVector, int topK) {
    SearchParam param = SearchParam.newBuilder()
        .withCollectionName("documents")
        .withVectorFieldName("embedding")
        .withTopK(topK)
        .withVectors(Arrays.asList(Arrays.asList(queryVector)))
        .withMetricType(MetricType.IP)  // 内积相似度
        .build();

    SearchResult result = client.search(param);

    for (SearchResult.ScoredVector sv : result.getRowRecords()) {
        System.out.println("ID: " + sv.getVector().get("id")
            + ", Score: " + sv.getScore()
            + ", Text: " + sv.getVector().get("text"));
    }
}

七、性能优化建议

  1. 选择合适的索引:HNSW 适合高精度场景,IVF_FLAT 适合大规模数据
  2. Partition 优化:按时间或类别分区,减少检索范围
  3. 批量操作:使用批量插入和批量检索,减少网络开销
  4. 内存管理:确保 Collection 加载到内存,避免磁盘 I/O

总结

Milvus 是构建生产级 RAG 系统的最佳选择。本文涵盖了从部署到 Java 集成的完整流程,下期我们来聊:如何用 Milvus + LangChain4j 构建完整的知识库问答系统

觉得有帮助请点赞收藏!有问题欢迎评论区交流 🚀

posted @ 2026-04-02 11:50  弥烟袅绕  阅读(0)  评论(0)    收藏  举报