Champ primaire et AutoID

Chaque collection dans Milvus doit avoir un champ primaire pour identifier de manière unique chaque entité. Ce champ garantit que chaque entité peut être insérée, mise à jour, interrogée ou supprimée sans ambiguïté.

En fonction de votre cas d'utilisation, vous pouvez laisser Milvus générer automatiquement des ID (AutoID) ou attribuer vos propres ID manuellement.

Qu'est-ce qu'un champ primaire ?

Un champ primaire sert de clé unique pour chaque entité d'une collection, comme une clé primaire dans une base de données traditionnelle. Milvus utilise le champ primaire pour gérer les entités pendant les opérations d'insertion, d'upsert, de suppression et de requête.

Exigences clés :

  • Chaque collection doit avoir exactement un champ primaire.

  • Les valeurs des champs primaires ne peuvent pas être nulles.

  • Le type de données doit être spécifié lors de la création et ne peut être modifié ultérieurement.

Types de données pris en charge

Le champ primaire doit utiliser un type de données scalaire pris en charge qui permet d'identifier les entités de manière unique.

Type de données

Description du type de données

INT64

Type entier 64 bits, couramment utilisé avec AutoID. Il s'agit de l'option recommandée pour la plupart des cas d'utilisation.

VARCHAR

Type de chaîne de longueur variable. À utiliser lorsque les identifiants d'entité proviennent de systèmes externes (par exemple, codes de produit ou identifiants d'utilisateur). Nécessite la propriété max_length pour définir le nombre maximal d'octets autorisés par valeur.

Choix entre AutoID et ID manuels

Milvus prend en charge deux modes d'affectation des valeurs de clé primaire.

Mode

Description

Recommandé pour

AutoID

Milvus génère automatiquement des identifiants uniques pour les entités insérées ou importées.

La plupart des scénarios dans lesquels il n'est pas nécessaire de gérer les identifiants manuellement.

ID manuel

Vous fournissez vous-même des identifiants uniques lors de l'insertion ou de l'importation de données.

Lorsque les identifiants doivent s'aligner sur des systèmes externes ou des ensembles de données préexistants.

  • Si vous ne savez pas quel mode choisir, commencez par AutoID pour une ingestion plus simple et une unicité garantie.

  • Il est conseillé d'utiliser autoId dans tous les cas, à moins que la définition manuelle des clés primaires ne soit bénéfique.

Démarrage rapide : Utiliser AutoID

Vous pouvez laisser Milvus gérer la génération d'ID automatiquement.

Etape 1 : Créer une collection avec AutoID

Activer auto_id=True dans la définition de votre champ primaire. Milvus se chargera automatiquement de la génération d'identifiants.

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
}"

Étape 2 : Insérer des données

Important : N'incluez pas la colonne du champ primaire dans vos données. Milvus génère les identifiants automatiquement.

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
}"

Utilisez upsert() au lieu de insert() lorsque vous travaillez avec des entités existantes afin d'éviter les erreurs de duplication d'ID.

Utiliser des ID manuels

Si vous avez besoin de contrôler les identifiants manuellement, désactivez AutoID et fournissez vos propres valeurs.

Étape 1 : Créer une collection sans 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
}"

Étape 2 : Insérer des données avec vos identifiants

Vous devez inclure la colonne du champ primaire dans chaque opération d'insertion.

# 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
}"

Vos responsabilités :

  • Veiller à ce que tous les identifiants soient uniques pour toutes les entités

  • Inclure le champ primaire dans chaque opération d'insertion/importation

  • Gérer vous-même les conflits d'identifiants et la détection des doublons

Utilisation avancée

Migrer des données avec des AutoID existants

Pour préserver les ID existants lors de la migration des données, activez la propriété allow_insert_auto_id en effectuant l'appel alter_collection_properties. Lorsque cette propriété est définie sur true, Milvus accepte les ID fournis par l'utilisateur même si l'AutoID est activé.

Pour plus de détails sur la configuration, voir Modifier la collecte.

Garantir l'unicité globale de l'AutoID dans les clusters

Lors de l'exécution de plusieurs clusters Milvus, configurer un ID de cluster unique pour chacun afin de s'assurer que les AutoID ne se chevauchent jamais.

Configuration : Modifiez la configuration common.clusterID dans milvus.yaml avant d'initialiser votre cluster :

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

Dans cette configuration, clusterID spécifie l'identifiant unique utilisé dans la génération de l'AutoID, allant de 0 à 7 (prend en charge jusqu'à huit clusters).

Milvus gère l'inversion des bits en interne pour permettre une expansion future sans chevauchement d'ID. Aucune configuration manuelle n'est nécessaire en dehors de la définition de l'ID du cluster.

Référence : Fonctionnement de l'AutoID

Comprendre comment AutoID génère des identifiants uniques en interne peut vous aider à configurer correctement les ID de clusters et à résoudre les problèmes liés aux ID.

AutoID utilise un format structuré de 64 bits pour garantir l'unicité :

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

Segment

Description de l'identifiant

sign_bit

Réservé à l'usage interne

cluster_id

Identifie le cluster qui a généré l'ID (plage de valeurs : 0-7)

physical_ts

Horodatage en millisecondes de la génération de l'ID

logical_ts

Compteur permettant de distinguer les ID créés dans la même milliseconde

Même lorsque AutoID est activé avec VARCHAR comme type de données, Milvus génère toujours des ID numériques. Ceux-ci sont stockés sous forme de chaînes numériques d'une longueur maximale de 20 caractères (plage uint64).