chat

背景

类似的,给出向量数据库的表字段+索引。

我初步想的,大概需要 gitHistoryCommit(提交记录);

gitHistoryFile(提交文件,冗余commitId);   

gitHistoryMethod(提交函数,冗余 fileId)。

每个字段都要有 repoId,时间。其他的你看着设计。

设计

向量数据库(Milvus)完整表设计(Java SDK 2.6.13)

一、表清单与原因

表名 对应图实体 需要原因
gitHistoryCommit GitHistoryCommit 提交级语义检索,用于“自然语言 → 提交”
gitHistoryFile GitHistoryFile 文件级语义检索,用于“功能描述 → 文件”
gitHistoryDiffHunk GitHistoryDiffHunk 细粒度变更块检索,用于“类似修改模式”的匹配(例如查找相似的 bug 修复片段)
gitHistoryMethod GitHistoryFunction 函数级语义检索,用于代码片段相似匹配、推荐相似实现

为什么需要 DiffHunk 表?
虽然 DiffHunk 是中间实体,但它的 newCodeoldCode 包含变更的具体内容,可以用于检索“历史上类似的修改”。例如:查找“所有增加空指针检查的 diff 块”,直接检索 diff hunk 比检索函数更精确。因此保留该表。


二、通用设计原则(Java SDK 2.6.13)

  • 分区键:所有表均以 repoId 作为分区键(isPartitionKey(true)),实现多仓库物理隔离。
  • 标量索引:对过滤字段(repoIdcommitHashfileIdmethodId、时间戳等)创建 INVERTED 索引。
  • 向量索引:使用 HNSW,度量类型 COSINE,参数 M=16efConstruction=200
  • 向量维度:1536(适配 text-embedding-3-small 等模型)。
  • 自动主键id 字段自增,类型 Int64

三、Collection 1: gitHistoryCommit

3.1 字段定义

字段名 类型 是否向量 说明 索引
id INT64 自增主键 主键
commitHash VARCHAR(40) 完整 commit SHA INVERTED
repoId VARCHAR(128) 仓库标识(分区键) INVERTED
authorTime INT64 提交时间戳(秒) INVERTED
summary VARCHAR(1024) 提交摘要(message + 变更文件列表)
embedding FLOAT_VECTOR(1536) 语义向量 HNSW(COSINE)

3.2 Java 创建代码

import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.index.request.CreateIndexReq;

public class CreateCommitCollection {
    public static void create(MilvusClientV2 client, String collectionName) {
        // 1. 定义 Schema
        CreateCollectionReq.CollectionSchema schema = client.createSchema();
        schema.addField(DataType.Int64, "id", true, true);  // 主键,自增
        schema.addField(DataType.VarChar, "commitHash", 40, false);
        schema.addField(DataType.VarChar, "repoId", 128, false).setPartitionKey(true);
        schema.addField(DataType.Int64, "authorTime", false);
        schema.addField(DataType.VarChar, "summary", 1024, false);
        schema.addField(DataType.FloatVector, "embedding", 1536, false);

        // 2. 创建 Collection
        CreateCollectionReq createReq = CreateCollectionReq.builder()
                .collectionName(collectionName)
                .collectionSchema(schema)
                .build();
        client.createCollection(createReq);

        // 3. 创建标量索引
        client.createIndex(CreateIndexReq.builder()
                .collectionName(collectionName)
                .fieldName("commitHash")
                .indexType(IndexParam.IndexType.INVERTED)
                .build());
        client.createIndex(CreateIndexReq.builder()
                .collectionName(collectionName)
                .fieldName("repoId")
                .indexType(IndexParam.IndexType.INVERTED)
                .build());
        client.createIndex(CreateIndexReq.builder()
                .collectionName(collectionName)
                .fieldName("authorTime")
                .indexType(IndexParam.IndexType.INVERTED)
                .build());

        // 4. 创建向量索引
        IndexParam indexParam = IndexParam.builder()
                .fieldName("embedding")
                .indexType(IndexParam.IndexType.HNSW)
                .metricType(IndexParam.MetricType.COSINE)
                .extraParam("M", 16)
                .extraParam("efConstruction", 200)
                .build();
        client.createIndex(CreateIndexReq.builder()
                .collectionName(collectionName)
                .indexParam(indexParam)
                .build());
    }
}

四、Collection 2: gitHistoryFile

4.1 字段定义

字段名 类型 是否向量 说明 索引
id INT64 自增主键 主键
fileId VARCHAR(512) 文件唯一标识({repoId}:{path} INVERTED
filePath VARCHAR(1024) 文件路径 INVERTED
repoId VARCHAR(128) 仓库标识(分区键) INVERTED
lastCommitHash VARCHAR(40) 最后修改的 commit hash INVERTED
language VARCHAR(32) 编程语言 INVERTED
updateTime INT64 解析时间戳(秒) INVERTED
description VARCHAR(2048) 文件描述(文件名+路径+主要类/函数摘要)
embedding FLOAT_VECTOR(1536) 语义向量 HNSW(COSINE)

4.2 Java 创建代码

public class CreateFileCollection {
    public static void create(MilvusClientV2 client, String collectionName) {
        CreateCollectionReq.CollectionSchema schema = client.createSchema();
        schema.addField(DataType.Int64, "id", true, true);
        schema.addField(DataType.VarChar, "fileId", 512, false);
        schema.addField(DataType.VarChar, "filePath", 1024, false);
        schema.addField(DataType.VarChar, "repoId", 128, false).setPartitionKey(true);
        schema.addField(DataType.VarChar, "lastCommitHash", 40, false);
        schema.addField(DataType.VarChar, "language", 32, false);
        schema.addField(DataType.Int64, "updateTime", false);
        schema.addField(DataType.VarChar, "description", 2048, false);
        schema.addField(DataType.FloatVector, "embedding", 1536, false);

        client.createCollection(CreateCollectionReq.builder()
                .collectionName(collectionName)
                .collectionSchema(schema)
                .build());

        // 标量索引
        for (String field : Arrays.asList("fileId", "filePath", "repoId", "lastCommitHash", "language", "updateTime")) {
            client.createIndex(CreateIndexReq.builder()
                    .collectionName(collectionName)
                    .fieldName(field)
                    .indexType(IndexParam.IndexType.INVERTED)
                    .build());
        }

        // 向量索引
        IndexParam indexParam = IndexParam.builder()
                .fieldName("embedding")
                .indexType(IndexParam.IndexType.HNSW)
                .metricType(IndexParam.MetricType.COSINE)
                .extraParam("M", 16)
                .extraParam("efConstruction", 200)
                .build();
        client.createIndex(CreateIndexReq.builder()
                .collectionName(collectionName)
                .indexParam(indexParam)
                .build());
    }
}

五、Collection 3: gitHistoryDiffHunk

5.1 字段定义

字段名 类型 是否向量 说明 索引
id INT64 自增主键 主键
diffId VARCHAR(512) diff 块唯一标识({commitHash}:{filePath}:{startLine} INVERTED
commitHash VARCHAR(40) 所属 commit hash INVERTED
filePath VARCHAR(1024) 所属文件路径 INVERTED
repoId VARCHAR(128) 仓库标识(分区键) INVERTED
changeType VARCHAR(16) add / delete / modify INVERTED
commitTime INT64 所属 commit 的时间戳(冗余,便于时间过滤) INVERTED
newCode VARCHAR(4096) 变更后的代码片段(可截断)
embedding FLOAT_VECTOR(1536) 语义向量(基于 newCode + changeType HNSW(COSINE)

5.2 Java 创建代码

public class CreateDiffHunkCollection {
    public static void create(MilvusClientV2 client, String collectionName) {
        CreateCollectionReq.CollectionSchema schema = client.createSchema();
        schema.addField(DataType.Int64, "id", true, true);
        schema.addField(DataType.VarChar, "diffId", 512, false);
        schema.addField(DataType.VarChar, "commitHash", 40, false);
        schema.addField(DataType.VarChar, "filePath", 1024, false);
        schema.addField(DataType.VarChar, "repoId", 128, false).setPartitionKey(true);
        schema.addField(DataType.VarChar, "changeType", 16, false);
        schema.addField(DataType.Int64, "commitTime", false);
        schema.addField(DataType.VarChar, "newCode", 4096, false);
        schema.addField(DataType.FloatVector, "embedding", 1536, false);

        client.createCollection(CreateCollectionReq.builder()
                .collectionName(collectionName)
                .collectionSchema(schema)
                .build());

        // 标量索引
        for (String field : Arrays.asList("diffId", "commitHash", "filePath", "repoId", "changeType", "commitTime")) {
            client.createIndex(CreateIndexReq.builder()
                    .collectionName(collectionName)
                    .fieldName(field)
                    .indexType(IndexParam.IndexType.INVERTED)
                    .build());
        }

        // 向量索引
        IndexParam indexParam = IndexParam.builder()
                .fieldName("embedding")
                .indexType(IndexParam.IndexType.HNSW)
                .metricType(IndexParam.MetricType.COSINE)
                .extraParam("M", 16)
                .extraParam("efConstruction", 200)
                .build();
        client.createIndex(CreateIndexReq.builder()
                .collectionName(collectionName)
                .indexParam(indexParam)
                .build());
    }
}

六、Collection 4: gitHistoryMethod

6.1 字段定义

字段名 类型 是否向量 说明 索引
id INT64 自增主键 主键
methodId VARCHAR(512) 函数唯一标识({fileId}:{name}:{startLine} INVERTED
methodName VARCHAR(256) 函数名 INVERTED
fileId VARCHAR(512) 所属文件 ID INVERTED
filePath VARCHAR(1024) 所属文件路径 INVERTED
repoId VARCHAR(128) 仓库标识(分区键) INVERTED
commitHash VARCHAR(40) 最近修改该函数的 commit hash INVERTED
signature VARCHAR(1024) 函数签名
bodySnippet VARCHAR(4096) 函数体代码片段(截断)
language VARCHAR(32) 编程语言 INVERTED
updateTime INT64 解析时间戳 INVERTED
embedding FLOAT_VECTOR(1536) 语义向量(基于 signature + bodySnippet HNSW(COSINE)

6.2 Java 创建代码

public class CreateMethodCollection {
    public static void create(MilvusClientV2 client, String collectionName) {
        CreateCollectionReq.CollectionSchema schema = client.createSchema();
        schema.addField(DataType.Int64, "id", true, true);
        schema.addField(DataType.VarChar, "methodId", 512, false);
        schema.addField(DataType.VarChar, "methodName", 256, false);
        schema.addField(DataType.VarChar, "fileId", 512, false);
        schema.addField(DataType.VarChar, "filePath", 1024, false);
        schema.addField(DataType.VarChar, "repoId", 128, false).setPartitionKey(true);
        schema.addField(DataType.VarChar, "commitHash", 40, false);
        schema.addField(DataType.VarChar, "signature", 1024, false);
        schema.addField(DataType.VarChar, "bodySnippet", 4096, false);
        schema.addField(DataType.VarChar, "language", 32, false);
        schema.addField(DataType.Int64, "updateTime", false);
        schema.addField(DataType.FloatVector, "embedding", 1536, false);

        client.createCollection(CreateCollectionReq.builder()
                .collectionName(collectionName)
                .collectionSchema(schema)
                .build());

        // 标量索引
        for (String field : Arrays.asList("methodId", "methodName", "fileId", "filePath", 
                                          "repoId", "commitHash", "language", "updateTime")) {
            client.createIndex(CreateIndexReq.builder()
                    .collectionName(collectionName)
                    .fieldName(field)
                    .indexType(IndexParam.IndexType.INVERTED)
                    .build());
        }

        // 向量索引
        IndexParam indexParam = IndexParam.builder()
                .fieldName("embedding")
                .indexType(IndexParam.IndexType.HNSW)
                .metricType(IndexParam.MetricType.COSINE)
                .extraParam("M", 16)
                .extraParam("efConstruction", 200)
                .build();
        client.createIndex(CreateIndexReq.builder()
                .collectionName(collectionName)
                .indexParam(indexParam)
                .build());
    }
}

七、向量生成策略汇总

输入内容 生成说明
gitHistoryCommit summary = message + " modified: " + 文件路径列表 调用 embedding 模型(如 OpenAI)
gitHistoryFile description = filePath + " language:" + language + 可选的主要类/函数名列表 同上
gitHistoryDiffHunk newCode + " type:" + changeType 截取前 4096 字符,避免超长
gitHistoryMethod signature + "\n" + bodySnippet 截取前 4096 字符

八、Java 插入数据示例(以 gitHistoryCommit 为例)

import io.milvus.v2.service.vector.request.InsertReq;
import java.util.*;

public class InsertCommit {
    public static void insert(MilvusClientV2 client, String collectionName) {
        List<Map<String, Object>> rows = new ArrayList<>();
        Map<String, Object> row = new HashMap<>();
        row.put("commitHash", "abc123");
        row.put("repoId", "myorg/myrepo");
        row.put("authorTime", 1700000000L);
        row.put("summary", "fix: 登录超时处理,修改了 auth.py");
        row.put("embedding", generateEmbedding("fix: 登录超时处理,修改了 auth.py")); // 1536维向量
        rows.add(row);
        
        InsertReq insertReq = InsertReq.builder()
                .collectionName(collectionName)
                .data(rows)
                .build();
        client.insert(insertReq);
    }
}

九、总结

  • 4 张表覆盖提交、文件、diff 块、函数四个粒度,满足不同层次的语义检索需求。
  • 冗余字段repoId(分区键)、commitTime(在 diff 表中)、updateTime 等,支持高效过滤。
  • 索引完备:标量字段使用 INVERTED 索引,向量字段使用 HNSW(COSINE)。
  • Java SDK 2.6.13 兼容的 API 风格(使用 MilvusClientV2CreateCollectionReq 等)。

此设计可直接用于批量解析脚本的向量入库逻辑。

参考资料