Первичное поле и автоидентификация

Каждая коллекция в Milvus должна иметь первичное поле для уникальной идентификации каждой сущности. Это поле гарантирует, что каждая сущность может быть вставлена, обновлена, запрошена или удалена без двусмысленности.

В зависимости от вашего случая использования вы можете либо позволить Milvus автоматически генерировать идентификаторы (AutoID), либо назначить свои собственные идентификаторы вручную.

Что такое первичное поле?

Первичное поле действует как уникальный ключ для каждой сущности в коллекции, подобно первичному ключу в традиционной базе данных. Milvus использует первичное поле для управления сущностями во время операций вставки, апсерт, удаления и запросов.

Ключевые требования:

  • Каждая коллекция должна иметь ровно одно первичное поле.

  • Значения первичного поля не могут быть нулевыми.

  • Тип данных должен быть указан при создании и не может быть изменен позднее.

Поддерживаемые типы данных

В первичном поле должен использоваться поддерживаемый скалярный тип данных, который может однозначно идентифицировать сущности.

Тип данных

Описание

INT64

64-битный целочисленный тип, обычно используемый в AutoID. Это рекомендуемый вариант для большинства случаев использования.

VARCHAR

Строковый тип переменной длины. Используется, когда идентификаторы сущностей поступают из внешних систем (например, коды продуктов или идентификаторы пользователей). Требуется свойство max_length для определения максимального количества байт, допустимого для одного значения.

Выбор между автоматическим и ручным присвоением идентификаторов

Milvus поддерживает два режима присвоения значений первичного ключа.

Режим

Описание

Рекомендуется для

AutoID

Milvus автоматически генерирует уникальные идентификаторы для вставленных или импортированных сущностей.

Большинство сценариев, в которых не нужно управлять идентификаторами вручную.

Ручной идентификатор

Вы сами создаете уникальные идентификаторы при вставке или импорте данных.

Когда идентификаторы должны быть согласованы с внешними системами или уже существующими наборами данных.

  • Если вы не уверены, какой режим выбрать, начните с AutoID - это упростит вставку и обеспечит гарантированную уникальность.

  • Рекомендуется полагаться на autoId во всех случаях, если только не требуется ручная установка первичных ключей.

Быстрый старт: Использование AutoID

Вы можете позволить Milvus генерировать идентификаторы автоматически.

Шаг 1: Создайте коллекцию с AutoID

Включите auto_id=True в определении первичного поля. Milvus будет автоматически обрабатывать генерацию идентификаторов.

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' \
-H 'Request-Timeout: 10' \
-d "{
    \"collectionName\": \"demo_autoid\",
    \"schema\": $SCHEMA
}"

Шаг 2: Вставка данных

Важно: Не включайте столбец первичного поля в свои данные. Milvus генерирует идентификаторы автоматически.

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' \
-H 'Request-Timeout: 10' \
-d "{
    \"collectionName\": \"demo_autoid\",
    \"data\": $INSERT_DATA
}"

Используйте upsert() вместо insert() при работе с существующими сущностями, чтобы избежать ошибок дублирования идентификаторов.

Использование ручных идентификаторов

Если вам нужно управлять идентификаторами вручную, отключите 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' \
-H 'Request-Timeout: 10' \
-d "{
    \"collectionName\": \"demo_manual_ids\",
    \"schema\": $SCHEMA
}"

Шаг 2: Вставьте данные с вашими идентификаторами

Вы должны включать столбец первичного поля в каждую операцию вставки.

# 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' \
-H 'Request-Timeout: 10' \
-d "{
    \"collectionName\": \"demo_manual_ids\",
    \"data\": $INSERT_DATA
}"

Ваши обязанности:

  • Убедитесь, что все идентификаторы уникальны для всех сущностей.

  • Включать первичное поле в каждую операцию вставки/импорта

  • Самостоятельно справляться с конфликтами идентификаторов и обнаружением дубликатов

Расширенное использование

Миграция данных с существующими автоидентификаторами

Чтобы сохранить существующие идентификаторы при миграции данных, включите свойство allow_insert_auto_id, выполнив вызов alter_collection_properties. Если установлено значение true, Milvus принимает идентификаторы, предоставленные пользователем, даже если включена функция AutoID.

Подробности настройки см. в разделе Изменить коллекцию.

Обеспечение уникальности глобального AutoID в кластерах

При работе нескольких кластеров Milvus настройте уникальный идентификатор кластера для каждого из них, чтобы AutoID никогда не пересекались.

Конфигурация: Перед инициализацией кластера отредактируйте конфигурацию common.clusterID в milvus.yaml:

common:
  clusterID: 3   # Must be unique across all clusters (Range: 0-7)

В этом конфиге clusterID указывается уникальный идентификатор, используемый при генерации AutoID, в диапазоне от 0 до 7 (поддерживается до восьми кластеров).

Milvus обрабатывает обратные биты внутри кластера, чтобы обеспечить будущее расширение без дублирования идентификаторов. Ручная настройка не требуется, кроме задания идентификатора кластера.

Ссылка: Как работает AutoID

Понимание того, как AutoID генерирует внутренние уникальные идентификаторы, поможет вам правильно настроить ID кластера и устранить проблемы, связанные с ID.

AutoID использует структурированный 64-битный формат, чтобы гарантировать уникальность:

[sign_bit][cluster_id][physical_ts][logical_ts]

Сегмент

Описание

sign_bit

Зарезервирован для внутреннего использования

cluster_id

Идентифицирует, какой кластер сгенерировал идентификатор (диапазон значений: 0-7)

physical_ts

Временная метка в миллисекундах, когда был сгенерирован идентификатор

logical_ts

Счетчик для различения идентификаторов, созданных в одну и ту же миллисекунду

Даже если включена функция AutoID с VARCHAR в качестве типа данных, Milvus все равно генерирует числовые идентификаторы. Они хранятся в виде числовых строк с максимальной длиной 20 символов (диапазон uint64).