Créer un champ StructArray

Créez un champ StructArray lorsqu'une entité doit contenir une liste ordonnée d'éléments structurés. Un champ StructArray est un champ Array dont le type d'élément est Struct. Chaque élément Struct suit le même schéma et peut contenir des sous-champs scalaires, des sous-champs vectoriels, ou les deux.

Cette page explique comment définir un schéma Struct, l’ajouter en tant que champ StructArray, choisir des sous-champs pour une recherche et un filtrage ultérieurs, et comprendre les règles de schéma applicables avant d’insérer ou d’indexer des données.

Avant de commencer

Cette page utilise une collection nommée « tech_articles ». Chaque entité représente un article technique, et le champ « chunks » stocke des données au niveau des blocs sous forme d’éléments Struct.

ChampTypeObjectif
doc_idINT64Clé primaire de l'article.
titleVARCHARTitre de l'article.
categoryVARCHARCatégorie au niveau de l'article.
title_vectorFLOAT_VECTORChamp vectoriel au niveau de l’article, utilisé ultérieurement dans les exemples de recherche hybride.
chunksARRAYChamp StructArray qui stocke le texte au niveau des segments, les métadonnées et les représentations vectorielles.

Le champ StructArray « chunks » contient les sous-champs suivants.

Sous-champTypeObjectif
textVARCHARTexte du bloc.
sectionVARCHARNom de la section, tel que « index », « search » ou « filter ».
pageINT64Numéro de page ou position logique du bloc.
quality_scoreFLOATScore au niveau du bloc utilisé dans le filtrage scalaire et les exemples de plage.
has_codeBOOLIndique si le segment contient du code.
emb_list_vectorFLOAT_VECTORSous-champ vectoriel pour la recherche dans EmbeddingList avec les métriques « MAX_SIM* ».
embFLOAT_VECTORSous-champ vectoriel pour la recherche au niveau des éléments avec des métriques vectorielles classiques.

Un champ vectoriel ou un sous-champ vectoriel n’accepte qu’un seul index. Si vous avez besoin à la fois d’une recherche EmbeddingList et d’une recherche au niveau des éléments, définissez deux sous-champs vectoriels distincts. Dans cet exemple, « chunks[emb_list_vector] » est destiné à la recherche EmbeddingList, et « chunks[emb] » à la recherche au niveau des éléments.

Types de données pris en charge pour les sous-champs

Un champ StructArray stocke une valeur de tableau pour chaque sous-champ Struct. Lorsque vous définissez un schéma Struct, choisissez les types de sous-champs parmi les familles scalaires et vectorielles prises en charge.

Type physique des sous-champs StructPrise en chargeRemarques
ArrayPrise en chargeDéfinissez le sous-champ comme suit : DataType.BOOL.
ArrayPrise en chargeDéfinissez le sous-champ comme suit : DataType.INT8, DataType.INT16, DataType.INT32 ou DataType.INT64.
ArrayPrise en chargeDéfinissez le sous-champ comme suit : DataType.FLOAT ou DataType.DOUBLE.
ArrayPrise en chargeDéfinissez le sous-champ comme suit : DataType.VARCHAR et définissez max_length.
ArrayOfVectorPris en chargeDéfinissez le sous-champ comme « DataType.FLOAT_VECTOR » et définissez « dim ».
ArrayOfVectorPrise en chargeDéfinissez le sous-champ comme « DataType.FLOAT16_VECTOR » et configurez « dim ».
ArrayOfVectorPrise en chargeDéfinissez le sous-champ comme « DataType.BFLOAT16_VECTOR » et configurez « dim ».
ArrayOfVectorPrise en chargeDéfinissez le sous-champ comme « DataType.INT8_VECTOR » et configurez « dim ».
ArrayOfVectorPrise en chargeDéfinissez le sous-champ comme « DataType.BINARY_VECTOR » et configurez « dim ».
ArrayOfVectorNon pris en chargeLes sous-champs de vecteurs clairsemés ne sont pas pris en charge dans les champs StructArray.
ArrayNon pris en chargeUtilisez « VARCHAR » et non « String ».
ArrayNon pris en chargeLes sous-champs JSON ne sont pas pris en charge dans les champs StructArray.
ArrayNon pris en chargeLes sous-champs de géométrie et les fonctions SIG ne sont pas pris en charge dans les champs StructArray.
ArrayNon pris en chargeLes sous-champs de type texte ne sont pas pris en charge dans les champs StructArray.
ArrayNon pris en chargeLes sous-champs « timestamptz » et les expressions spécifiques à l'heure ne sont pas pris en charge dans les champs StructArray.
Array, ArrayOfVector, Struct ou ArrayOfStructNon pris en chargeUn champ StructArray ne peut pas contenir de tableaux imbriqués, de tableaux vectoriels imbriqués, de champs Struct imbriqués ou de champs Array-of-Struct imbriqués.

Pour connaître la prise en charge spécifique à chaque version, le comportement des valeurs nullables et d’autres limites, consultez la section Limites de StructArray.

Créer une collection avec un champ StructArray

Pour créer un champ StructArray, définissez d’abord le schéma Struct utilisé par chaque élément. Ajoutez ensuite un champ Array et définissez son type d’élément sur Struct.

  1. Créez le schéma de la collection.

  2. Ajoutez des champs au niveau de la collection, tels que la clé primaire et les champs au niveau de l'article.

  3. Créez un schéma Struct pour les éléments stockés dans le champ StructArray.

  4. Ajoutez des sous-champs scalaires et vectoriels au schéma Struct.

  5. Ajoutez un champ « Array » avec l'element_type=DataType.STRUCT.

  6. Définissez ` struct_schema ` sur le schéma `Struct`.

  7. Définissez l'max_capacity pour limiter le nombre d'éléments Struct que chaque entité peut stocker dans le champ.

from pymilvus import MilvusClient, DataType

client = MilvusClient(
    uri="http://localhost:19530",
    token="root:Milvus",
)

schema = client.create_schema(
    auto_id=False,
    enable_dynamic_field=False,
)

# Collection-level fields.
schema.add_field(
    field_name="doc_id",
    datatype=DataType.INT64,
    is_primary=True,
)
schema.add_field(
    field_name="title",
    datatype=DataType.VARCHAR,
    max_length=512,
)
schema.add_field(
    field_name="category",
    datatype=DataType.VARCHAR,
    max_length=128,
)
schema.add_field(
    field_name="title_vector",
    datatype=DataType.FLOAT_VECTOR,
    dim=4,
)

# Struct schema used by each element in the StructArray field.
chunk_schema = client.create_struct_field_schema()
chunk_schema.add_field(
    field_name="text",
    datatype=DataType.VARCHAR,
    max_length=65535,
)
chunk_schema.add_field(
    field_name="section",
    datatype=DataType.VARCHAR,
    max_length=128,
)
chunk_schema.add_field(
    field_name="page",
    datatype=DataType.INT64,
)
chunk_schema.add_field(
    field_name="quality_score",
    datatype=DataType.FLOAT,
)
chunk_schema.add_field(
    field_name="has_code",
    datatype=DataType.BOOL,
)

# Vector subfield for EmbeddingList search.
chunk_schema.add_field(
    field_name="emb_list_vector",
    datatype=DataType.FLOAT_VECTOR,
    dim=4,
)

# Vector subfield for element-level search.
chunk_schema.add_field(
    field_name="emb",
    datatype=DataType.FLOAT_VECTOR,
    dim=4,
)

# Add the StructArray field.
schema.add_field(
    field_name="chunks",
    datatype=DataType.ARRAY,
    element_type=DataType.STRUCT,
    struct_schema=chunk_schema,
    max_capacity=1000,
)

client.create_collection(
    collection_name="tech_articles",
    schema=schema,
)

Comprendre les chemins d’accès aux champs StructArray

Une fois que vous avez créé un champ StructArray, faites référence à ses sous-champs à l’aide de la syntaxe de chemin d’accès « structArray[subfield] ». Utilisez cette syntaxe lorsque vous créez des index, effectuez des recherches dans des sous-champs vectoriels, générez des sous-champs de sortie ou créez des filtres scalaires.

CheminSignificationUtilisation courante
chunks[text]Le sous-champ « text » à l’intérieur de chaque élément Struct.Champ de sortie ou filtrage scalaire.
chunks[section]L'étiquette de section pour chaque bloc.Filtrage scalaire.
chunks[quality_score]Le score de qualité au niveau du bloc.Filtrage scalaire ou indice scalaire.
chunks[emb_list_vector]Le sous-champ vectoriel utilisé comme liste d'intégration.Recherche dans EmbeddingList avec l'MAX_SIM*.
chunks[emb]Le sous-champ vectoriel utilisé indépendamment par chaque élément Struct.Recherche vectorielle au niveau des éléments.

Rendre un champ StructArray non nul

Milvus v3.0.x prend en charge les champs StructArray pouvant prendre la valeur null. Un champ StructArray pouvant prendre la valeur null permet à une entité de stocker des valeurs « null » pour l’ensemble du champ StructArray.

schema.add_field(
    field_name="chunks",
    datatype=DataType.ARRAY,
    element_type=DataType.STRUCT,
    struct_schema=chunk_schema,
    max_capacity=1000,
    nullable=True,
)

Avertissement Les champs StructArray pouvant prendre la valeur null ne sont disponibles que dans Milvus v3.0.x. Pour un champ StructArray pouvant prendre la valeur null, une entité peut fournir une valeur StructArray valide ou définir l’ensemble du champ sur « null ». Lors de l’insertion d’une valeur StructArray valide, tous les sous-champs doivent être soit nuls, soit avoir des valeurs valides. L'insertion d'une entité dont certains sous-champs sont définis sur null et d'autres sur des valeurs valides entraîne une erreur. Pour plus de détails, consultez la section « Limites de StructArray ».

Ajouter un champ StructArray à une collection existante

Milvus v3.0.x prend en charge l’ajout d’un champ StructArray à une collection existante. Le champ StructArray ajouté doit être nullable, car les entités qui existent déjà dans la collection ne possèdent pas de valeurs pour ce nouveau champ.

Pour ajouter un champ StructArray à une collection existante, définissez d’abord le schéma Struct. Appelez ensuite la méthode ` add_collection_struct_field() ` et définissez ` nullable=True`.

chunk_schema = client.create_struct_field_schema()
chunk_schema.add_field(
    field_name="text",
    datatype=DataType.VARCHAR,
    max_length=65535,
)
chunk_schema.add_field(
    field_name="section",
    datatype=DataType.VARCHAR,
    max_length=128,
)
chunk_schema.add_field(
    field_name="page",
    datatype=DataType.INT64,
)
chunk_schema.add_field(
    field_name="quality_score",
    datatype=DataType.FLOAT,
)
chunk_schema.add_field(
    field_name="has_code",
    datatype=DataType.BOOL,
)
chunk_schema.add_field(
    field_name="emb_list_vector",
    datatype=DataType.FLOAT_VECTOR,
    dim=4,
)
chunk_schema.add_field(
    field_name="emb",
    datatype=DataType.FLOAT_VECTOR,
    dim=4,
)

client.add_collection_struct_field(
    collection_name="tech_articles",
    field_name="chunks",
    struct_schema=chunk_schema,
    max_capacity=1000,
    nullable=True,
)

Une fois le champ StructArray ajouté, les entités existantes renvoient ` null ` pour le nouveau champ, pour l’ensemble de ses sous-champs.

Une fois qu’un champ StructArray a été créé, vous ne pouvez plus ajouter de nouveaux sous-champs à ce champ StructArray existant. Si vous avez besoin d’attributs d’élément supplémentaires ultérieurement, appelez ` drop_collection_field() ` pour supprimer le champ StructArray, puis ajoutez un nouveau champ StructArray avec le schéma Struct mis à jour.

client.drop_collection_field(
    collection_name="tech_articles",
    field_name="chunks",
)

client.add_collection_struct_field(
    collection_name="tech_articles",
    field_name="chunks",
    struct_schema=updated_chunk_schema,
    max_capacity=1000,
    nullable=True,
)

Règles de schéma

RègleExplication
Struct est utilisé comme type d’élément Array.Créez un champ StructArray en tant que champ de type Array à l'aide de la méthode element_type=STRUCT. Ne créez pas de champ Struct en tant que champ de collection de niveau supérieur.
Tous les éléments partagent un même schéma.Chaque élément Struct du même champ StructArray respecte le schéma Struct défini pour ce champ.
max_capacity est obligatoire.Il limite le nombre d’éléments Struct que chaque entité peut stocker dans le champ StructArray.
Seuls les types de sous-champs pris en charge sont autorisés.Utilisez les types de sous-champs scalaires et vectoriels pris en charge par StructArray. Ne définissez pas de sous-champs JSON, Geometry, Text, Timestamptz, SparseFloatVector, ni de sous-champs Struct / Array imbriqués.
Les sous-champs vectoriels nécessitent des index avant la recherche.Créez des index sur des chemins tels que chunks[emb_list_vector] ou chunks[emb] avant d’exécuter une recherche vectorielle.
Un sous-champ vectoriel dispose d’un seul index.Si vous avez besoin à la fois d’une recherche EmbeddingList et d’une recherche au niveau des éléments, créez deux sous-champs vectoriels distincts.
Les sous-champs StructArray existants sont fixes.Une fois un champ StructArray créé, vous ne pouvez plus y ajouter de sous-champs.
Les fonctions ne sont pas prises en charge à l’intérieur de Struct.Ne définissez pas de fonctions pour les champs ou les sous-champs à l’intérieur d’un champ StructArray.
Les sous-champs scalaires doivent répondre aux besoins de filtrage.N'ajoutez des champs tels que section, quality_score ou has_code que si vous avez besoin de les filtrer, de les regrouper ou de les afficher ultérieurement.

Erreurs courantes

  • Créer DataType.STRUCT en tant que champ de collection de niveau supérieur au lieu de l’utiliser comme type d’élément d’un champ Array.

  • Oublier de définir « max_capacity » sur le champ StructArray.

  • Définir des types de sous-champs non pris en charge, tels que JSON, Geometry, Text, Timestamptz, SparseFloatVector, Array imbriqué, Struct imbriqué ou Array-of-Struct.

  • Utilisation de « String » comme type de sous-champ. Utilisez « VARCHAR » et définissez « max_length ».

  • Utilisation d’un seul sous-champ vectoriel à la fois pour la recherche dans EmbeddingList et la recherche au niveau des éléments.

  • Ajouter uniquement des sous-champs vectoriels et omettre les sous-champs scalaires nécessaires au filtrage, tels que section, quality_score ou has_code.

  • Considérer les sous-champs vectoriels comme des entrées de prédicats scalaires de type $[...]. Utiliser les sous-champs vectoriels pour la recherche vectorielle, et les sous-champs scalaires pour les prédicats scalaires.

  • Partir du principe que de nouveaux sous-champs peuvent être ajoutés à un champ StructArray existant après la création de ce dernier.

  • Utilisation de chunks.emb ou chunks.emb_list_vector au lieu de la syntaxe de chemin requise chunks[emb] ou chunks[emb_list_vector].

  • Considérer que le comportement des StructArray pouvant prendre la valeur null est disponible dans toutes les versions cibles.

Étapes suivantes

  1. Pour insérer des données imbriquées dans le champ StructArray, consultez la section Insérer des données dans les champs StructArray.

  2. Pour créer des index vectoriels et scalaires, consultez la section « Indexer des champs StructArray ».

  3. Pour effectuer une recherche dans les sous-champs vectoriels de StructArray, consultez la section « Recherche vectorielle de base avec StructArray ».

  4. Pour connaître les types de données pris en charge, le comportement des valeurs pouvant être nulles et les limitations spécifiques à chaque version, consultez la section « Limites de StructArray ».