主字段和自動識別
Milvus 中的每個集合都必須有一個主字段來唯一識別每個實體。這個欄位確保每個實體都可以被插入、更新、查詢或刪除,而不會產生歧義。
根據您的使用情況,您可以讓 Milvus 自動產生 ID(AutoID)或手動分配您自己的 ID。
什麼是主字段?
主字段是集合中每個實體的唯一鍵,類似於傳統數據庫中的主鍵。Milvus 在插入、上移、刪除和查詢操作中使用主字段來管理實體。
關鍵要求:
每個集合必須有一個主字段。
主字段值不能為空。
資料類型必須在建立時指定,且不能在之後更改。
支援的資料類型
主欄位必須使用可唯一識別實體的支援標量資料類型。
資料類型 |
說明 |
|---|---|
|
64 位整數類型,通常與 AutoID 一起使用。這是大多數使用個案的建議選項。 |
|
可變長度字串類型。如果實體識別碼來自外部系統(例如產品代碼或使用者 ID),請使用此類型。需要 |
選擇自動識別碼和手動識別碼
Milvus 支援兩種模式來指定主鍵值。
模式 |
說明 |
建議 |
|---|---|---|
自動識別 |
Milvus 自動為插入或匯入的實體產生唯一的 ID。 |
不需要手動管理 ID 的大多數情況。 |
手動 ID |
當插入或匯入資料時,您自己提供唯一的 ID。 |
當 ID 必須與外部系統或預先存在的資料集一致時。 |
如果您不確定要選擇哪一種模式,請從 AutoID 開始,因為它可以簡化擷取,並保證唯一性。
除非手動設定主鍵有好處,否則建議您在所有情況下都依賴
autoId。
快速入門:使用自動識別
你可以讓 Milvus 自動處理 ID 的產生。
步驟 1: 使用 AutoID 建立一個集合
在您的主欄位定義中啟用auto_id=True 。Milvus 會自動處理 ID 的產生。
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
schema = client.create_schema()
# Define primary field with AutoID enabled
schema.add_field(
field_name="id", # Primary field name
is_primary=True,
auto_id=True, # Milvus generates IDs automatically; Defaults to False
datatype=DataType.INT64
)
# Define the other fields
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=4) # Vector field
schema.add_field(field_name="category", datatype=DataType.VARCHAR, max_length=1000) # Scalar field of the VARCHAR type
# Create the collection
if client.has_collection("demo_autoid"):
client.drop_collection("demo_autoid")
client.create_collection(collection_name="demo_autoid", schema=schema)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.collection.request.DropCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
CreateCollectionReq.CollectionSchema collectionSchema = CreateCollectionReq.CollectionSchema.builder()
.build();
collectionSchema.addField(AddFieldReq.builder()
.fieldName("id")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.autoID(true)
.build());
collectionSchema.addField(AddFieldReq.builder()
.fieldName("embedding")
.dataType(DataType.FloatVector)
.dimension(4)
.build());
collectionSchema.addField(AddFieldReq.builder()
.fieldName("category")
.dataType(DataType.VarChar)
.maxLength(1000)
.build());
client.dropCollection(DropCollectionReq.builder()
.collectionName("demo_autoid")
.build());
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("demo_autoid")
.collectionSchema(collectionSchema)
.build();
client.createCollection(requestCreate);
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({
address: "localhost:19530",
});
// Define schema fields
const schema = [
{
name: "id",
description: "Primary field",
data_type: DataType.Int64,
is_primary_key: true,
autoID: true, // Milvus generates IDs automatically
},
{
name: "embedding",
description: "Vector field",
data_type: DataType.FloatVector,
dim: 4,
},
{
name: "category",
description: "Scalar field",
data_type: DataType.VarChar,
max_length: 1000,
},
];
// Create the collection
await client.createCollection({
collection_name: "demo_autoid",
fields: schema,
});
// go
# restful
export SCHEMA='{
"autoID": true,
"fields": [
{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true,
"elementTypeParams": {}
},
{
"fieldName": "embedding",
"dataType": "FloatVector",
"isPrimary": false,
"elementTypeParams": {
"dim": "4"
}
},
{
"fieldName": "category",
"dataType": "VarChar",
"isPrimary": false,
"elementTypeParams": {
"max_length": "1000"
}
}
]
}'
curl -X POST 'http://localhost:19530/v2/vectordb/collections/create' \
-H 'Content-Type: application/json' \
-d "{
\"collectionName\": \"demo_autoid\",
\"schema\": $SCHEMA
}"
步驟 2:插入資料
重要:請勿在您的資料中包含主欄位欄位。Milvus 會自動產生 ID。
data = [
{"embedding": [0.1, 0.2, 0.3, 0.4], "category": "book"},
{"embedding": [0.2, 0.3, 0.4, 0.5], "category": "toy"},
]
res = client.insert(collection_name="demo_autoid", data=data)
print("Generated IDs:", res.get("ids"))
# Output example:
# Generated IDs: [461526052788333649, 461526052788333650]
import com.google.gson.*;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;
List<JsonObject> rows = new ArrayList<>();
Gson gson = new Gson();
JsonObject row1 = new JsonObject();
row1.add("embedding", gson.toJsonTree(new float[]{0.1f, 0.2f, 0.3f, 0.4f}));
row1.addProperty("category", "book");
rows.add(row1);
JsonObject row2 = new JsonObject();
row2.add("embedding", gson.toJsonTree(new float[]{0.2f, 0.3f, 0.4f, 0.5f}));
row2.addProperty("category", "toy");
rows.add(row2);
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("demo_autoid")
.data(rows)
.build());
System.out.printf("Generated IDs: %s\n", insertR.getPrimaryKeys());
const data = [
{"embedding": [0.1, 0.2, 0.3, 0.4], "category": "book"},
{"embedding": [0.2, 0.3, 0.4, 0.5], "category": "toy"},
];
const res = await client.insert({
collection_name: "demo_autoid",
fields_data: data,
});
console.log(res);
// go
# restful
export INSERT_DATA='[
{
"embedding": [0.1, 0.2, 0.3, 0.4],
"category": "book"
},
{
"embedding": [0.2, 0.3, 0.4, 0.5],
"category": "toy"
}
]'
curl -X POST 'http://localhost:19530/v2/vectordb/entities/insert' \
-H 'Content-Type: application/json' \
-d "{
\"collectionName\": \"demo_autoid\",
\"data\": $INSERT_DATA
}"
使用現有實體時,請使用upsert() 而非insert() ,以避免 ID 重複錯誤。
使用手動 ID
如果您需要手動控制 ID,請停用 AutoID 並提供您自己的值。
步驟 1:建立一個沒有 AutoID 的集合
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
schema = client.create_schema()
# Define the primary field without AutoID
schema.add_field(
field_name="product_id",
is_primary=True,
auto_id=False, # You'll provide IDs manually at data ingestion
datatype=DataType.VARCHAR,
max_length=100 # Required when datatype is VARCHAR
)
# Define the other fields
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=4) # Vector field
schema.add_field(field_name="category", datatype=DataType.VARCHAR, max_length=1000) # Scalar field of the VARCHAR type
# Create the collection
if client.has_collection("demo_manual_ids"):
client.drop_collection("demo_manual_ids")
client.create_collection(collection_name="demo_manual_ids", schema=schema)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.collection.request.DropCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
CreateCollectionReq.CollectionSchema collectionSchema = CreateCollectionReq.CollectionSchema.builder()
.build();
collectionSchema.addField(AddFieldReq.builder()
.fieldName("product_id")
.dataType(DataType.VarChar)
.isPrimaryKey(true)
.autoID(false)
.maxLength(100)
.build());
collectionSchema.addField(AddFieldReq.builder()
.fieldName("embedding")
.dataType(DataType.FloatVector)
.dimension(4)
.build());
collectionSchema.addField(AddFieldReq.builder()
.fieldName("category")
.dataType(DataType.VarChar)
.maxLength(1000)
.build());
client.dropCollection(DropCollectionReq.builder()
.collectionName("demo_manual_ids")
.build());
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("demo_manual_ids")
.collectionSchema(collectionSchema)
.build();
client.createCollection(requestCreate);
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({
address: "localhost:19530",
username: "username",
password: "Aa12345!!",
});
const schema = [
{
name: "product_id",
data_type: DataType.VARCHAR,
is_primary_key: true,
autoID: false,
},
{
name: "embedding",
data_type: DataType.FLOAT_VECTOR,
dim: 4,
},
{
name: "category",
data_type: DataType.VARCHAR,
max_length: 1000,
},
];
const res = await client.createCollection({
collection_name: "demo_autoid",
schema: schema,
});
// go
# restful
export SCHEMA='{
"autoID": false,
"fields": [
{
"fieldName": "product_id",
"dataType": "VarChar",
"isPrimary": true,
"elementTypeParams": {
"max_length": "100"
}
},
{
"fieldName": "embedding",
"dataType": "FloatVector",
"isPrimary": false,
"elementTypeParams": {
"dim": "4"
}
},
{
"fieldName": "category",
"dataType": "VarChar",
"isPrimary": false,
"elementTypeParams": {
"max_length": "1000"
}
}
]
}'
curl -X POST 'http://localhost:19530/v2/vectordb/collections/create' \
-H 'Content-Type: application/json' \
-d "{
\"collectionName\": \"demo_manual_ids\",
\"schema\": $SCHEMA
}"
步驟 2:使用您的 ID 插入資料
您必須在每次插入操作中包含主欄位欄位。
# Each entity must contain the primary field `product_id`
data = [
{"product_id": "PROD-001", "embedding": [0.1, 0.2, 0.3, 0.4], "category": "book"},
{"product_id": "PROD-002", "embedding": [0.2, 0.3, 0.4, 0.5], "category": "toy"},
]
res = client.insert(collection_name="demo_manual_ids", data=data)
print("Generated IDs:", res.get("ids"))
# Output example:
# Generated IDs: ['PROD-001', 'PROD-002']
import com.google.gson.*;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;
List<JsonObject> rows = new ArrayList<>();
Gson gson = new Gson();
JsonObject row1 = new JsonObject();
row1.addProperty("product_id", "PROD-001");
row1.add("embedding", gson.toJsonTree(new float[]{0.1f, 0.2f, 0.3f, 0.4f}));
row1.addProperty("category", "book");
rows.add(row1);
JsonObject row2 = new JsonObject();
row2.addProperty("product_id", "PROD-002");
row2.add("embedding", gson.toJsonTree(new float[]{0.2f, 0.3f, 0.4f, 0.5f}));
row2.addProperty("category", "toy");
rows.add(row2);
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("demo_manual_ids")
.data(rows)
.build());
System.out.printf("Generated IDs: %s\n", insertR.getPrimaryKeys());
const data = [
{"product_id": "PROD-001", "embedding": [0.1, 0.2, 0.3, 0.4], "category": "book"},
{"product_id": "PROD-002", "embedding": [0.2, 0.3, 0.4, 0.5], "category": "toy"},
];
const insert = await client.insert({
collection_name: "demo_autoid",
fields_data: data,
});
console.log(insert);
// go
# restful
export INSERT_DATA='[
{
"product_id": "PROD-001",
"embedding": [0.1, 0.2, 0.3, 0.4],
"category": "book"
},
{
"product_id": "PROD-002",
"embedding": [0.2, 0.3, 0.4, 0.5],
"category": "toy"
}
]'
# 插入数据
curl -X POST 'http://localhost:19530/v2/vectordb/entities/insert' \
-H 'Content-Type: application/json' \
-d "{
\"collectionName\": \"demo_manual_ids\",
\"data\": $INSERT_DATA
}"
您的責任
確保所有 ID 在所有實體中都是唯一的
在每次插入/導入作業中包含主欄位
自行處理 ID 衝突和重複檢測
進階用法
使用現有的 AutoID 遷移資料
要在資料遷移過程中保留現有的 ID,請透過alter_collection_properties 呼叫啟用allow_insert_auto_id 屬性。當設定為 true 時,即使 AutoID 已啟用,Milvus 仍會接受使用者提供的 ID。
有關設定的詳細資訊,請參閱修改集合。
確保全域 AutoID 在集群間的唯一性
當執行多個 Milvus 集群時,為每個集群配置一個唯一的集群 ID,以確保 AutoID 永遠不會重疊。
配置:在初始化群集之前,編輯milvus.yaml 中的common.clusterID config:
common:
clusterID: 3 # Must be unique across all clusters (Range: 0-7)
在此配置中,clusterID 指定 AutoID 生成中使用的唯一标识符,范围从 0 到 7(最多支持 8 个群集)。
Milvus 會在內部處理位元反轉,以便未來擴充時不會出現 ID 重疊的情況。除了設定群集 ID 外,不需要手動設定。
參考:AutoID 如何運作
瞭解 AutoID 如何在內部產生唯一識別碼,可協助您正確設定群集 ID,並排除 ID 相關問題。
AutoID 使用結構化的 64 位元格式來保證唯一性:
[sign_bit][cluster_id][physical_ts][logical_ts]
區段 |
說明 |
|---|---|
|
保留給內部使用 |
|
識別產生 ID 的群集 (值範圍:0-7) |
|
以毫秒為單位的 ID 產生時間戳記 |
|
用來區分在同一毫秒內產生的 ID 的計數器 |
即使啟用 AutoID 並以VARCHAR 作為資料類型,Milvus 仍會產生數值 ID。這些 ID 儲存為最大長度為 20 個字元(uint64 範圍)的數字字串。