• À propos de Milvus
  • Commencer
  • Concepts
  • Guide de l'utilisateur
  • Importation de données
  • Outils d'IA
  • Guide d'administration
  • Outils
  • Intégrations
  • Tutoriels
  • FAQ
  • API Reference

Champ JSON

Milvus vous permet de stocker et d'indexer des données structurées dans un champ unique à l'aide du type de données JSON. Cela permet des schémas flexibles avec des attributs imbriqués tout en permettant un filtrage efficace via l'indexation JSON.

Qu'est-ce qu'un champ JSON ?

Un champ JSON est un champ défini par un schéma dans Milvus qui stocke des données clé-valeur structurées. Les valeurs peuvent être des chaînes, des nombres, des booléens, des tableaux ou des objets profondément imbriqués.

Voici un exemple de ce à quoi peut ressembler un champ JSON dans un document :

{
  "metadata": {
    "category": "electronics",
    "brand": "BrandA",
    "in_stock": true,
    "price": 99.99,
    "string_price": "99.99",
    "tags": ["clearance", "summer_sale"],
    "supplier": {
      "name": "SupplierX",
      "country": "USA",
      "contact": {
        "email": "support@supplierx.com",
        "phone": "+1-800-555-0199"
      }
    }
  }
}

Dans cet exemple :

  • metadata est le champ JSON défini dans le schéma.

  • Vous pouvez stocker des valeurs plates (par exemple category, in_stock), des tableaux (tags) et des objets imbriqués (supplier).

Définir un champ JSON dans le schéma

Pour utiliser un champ JSON, définissez-le explicitement dans le schéma de la collection en spécifiant DataType comme JSON.

L'exemple ci-dessous crée une collection dont le schéma contient ces champs :

  • La clé primaire (product_id)

  • Un champ vector (obligatoire pour chaque collection)

  • Un champ metadata de type JSON, qui peut stocker des données structurées telles que des valeurs plates, des tableaux ou des objets imbriqués.

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost:19530")

# Create schema with a JSON field
schema = client.create_schema(auto_id=False, enable_dynamic_field=True)

schema.add_field(field_name="product_id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5)
schema.add_field(field_name="metadata", datatype=DataType.JSON, nullable=True)  # JSON field that allows null values

client.create_collection(
    collection_name="product_catalog",
    schema=schema
)
import io.milvus.v2.client.*;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.collection.request.AddFieldReq;

ConnectConfig config = ConnectConfig.builder()
        .uri("http://localhost:19530")
        .build();
MilvusClientV2 client = new MilvusClientV2(config);

CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder()
        .enableDynamicField(true)
        .build();
        
schema.addField(AddFieldReq.builder()
        .fieldName("product_id")
        .dataType(DataType.Int64)
        .isPrimaryKey(Boolean.TRUE)
        .build());
schema.addField(AddFieldReq.builder()
        .fieldName("vector")
        .dataType(DataType.FloatVector)
        .dimension(5)
        .build());
schema.addField(AddFieldReq.builder()
        .fieldName("metadata")
        .dataType(DataType.JSON)
        .isNullable(true)
        .build());
        
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
        .collectionName("product_catalog")
        .collectionSchema(schema)
        .build();
client.createCollection(requestCreate);
import { MilvusClient, DataType } from '@zilliz/milvus2-sdk-node';

const client = new MilvusClient({
  address: 'localhost:19530'
});

// Create collection
await client.createCollection({
collection_name: "product_catalog",
fields: [
  {
    name: "product_id",
    data_type: DataType.Int64,
    is_primary_key: true,
    autoID: false
  },
  {
    name: "vector",
    data_type: DataType.FloatVector,
    dim: 5
  },
  {
    name: "metadata",
    data_type: DataType.JSON,
    nullable: true  // JSON field that allows null values
  }
],
enable_dynamic_field: true
});

import (
    "context"

    "github.com/milvus-io/milvus/client/v2/entity"
    "github.com/milvus-io/milvus/client/v2/milvusclient"
)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
    Address: "localhost:19530",
})
if err != nil {
    return err
}

schema := entity.NewSchema().WithDynamicFieldEnabled(true)
schema.WithField(entity.NewField().
    WithName("product_id").pk
    WithDataType(entity.FieldTypeInt64).
    WithIsPrimaryKey(true),
).WithField(entity.NewField().
    WithName("vector").
    WithDataType(entity.FieldTypeFloatVector).
    WithDim(5),
).WithField(entity.NewField().
    WithName("metadata").
    WithDataType(entity.FieldTypeJSON).
    WithNullable(true),
)

err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("product_catalog", schema))
if err != nil {
    return err
}
# restful
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"

# 字段定义
export productIdField='{
  "fieldName": "product_id",
  "dataType": "Int64",
  "isPrimary": true,
  "autoID": false
}'

export vectorField='{
  "fieldName": "vector",
  "dataType": "FloatVector",
  "typeParams": {
    "dim": 5
  }
}'

export metadataField='{
  "fieldName": "metadata",
  "dataType": "JSON",
  "isNullable": true
}'

# 构造 schema
export schema="{
  \"autoID\": false,
  \"enableDynamicField\": true,
  \"fields\": [
    $productIdField,
    $vectorField,
    $metadataField
  ]
}"

# 创建集合
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
  \"collectionName\": \"product_catalog\",
  \"schema\": $schema
}"

Vous pouvez également activer la fonctionnalité de champ dynamique pour stocker des champs non déclarés de manière flexible, mais cela n'est pas nécessaire pour que les champs JSON fonctionnent. Pour plus d'informations, voir Champ dynamique.

Insérer des entités avec des données JSON

Une fois la collection créée, insérez des entités contenant des objets JSON structurés dans le champ JSON metadata.

entities = [
    {
        "product_id": 1,
        "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
        "metadata": {
            "category": "electronics",
            "brand": "BrandA",
            "in_stock": True,
            "price": 99.99,
            "string_price": "99.99",
            "tags": ["clearance", "summer_sale"],
            "supplier": {
                "name": "SupplierX",
                "country": "USA",
                "contact": {
                    "email": "support@supplierx.com",
                    "phone": "+1-800-555-0199"
                }
            }
        }
    }
]

client.insert(collection_name="product_catalog", data=entities)
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import io.milvus.v2.service.vector.request.InsertReq;

Gson gson = new Gson();
JsonObject row = new JsonObject();
row.addProperty("product_id", 1);
row.add("vector", gson.toJsonTree(Arrays.asList(0.1, 0.2, 0.3, 0.4, 0.5)));

JsonObject metadata = new JsonObject();
metadata.addProperty("category", "electronics");
metadata.addProperty("brand", "BrandA");
metadata.addProperty("in_stock", true);
metadata.addProperty("price", 99.99);
metadata.addProperty("string_price", "99.99");
metadata.add("tags", gson.toJsonTree(Arrays.asList("clearance", "summer_sale")));

JsonObject supplier = new JsonObject();
supplier.addProperty("name", "SupplierX");
supplier.addProperty("country", "USA");

JsonObject contact = new JsonObject();
contact.addProperty("email", "support@supplierx.com");
contact.addProperty("phone", "+1-800-555-0199");

supplier.add("contact", contact);
metadata.add("supplier", supplier);
row.add("metadata", metadata);

client.insert(InsertReq.builder()
        .collectionName("product_catalog")
        .data(Collections.singletonList(row))
        .build());
const entities = [
    {
        "product_id": 1,
        "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
        "metadata": {
            "category": "electronics",
            "brand": "BrandA",
            "in_stock": True,
            "price": 99.99,
            "string_price": "99.99",
            "tags": ["clearance", "summer_sale"],
            "supplier": {
                "name": "SupplierX",
                "country": "USA",
                "contact": {
                    "email": "support@supplierx.com",
                    "phone": "+1-800-555-0199"
                }
            }
        }
    }
]

await client.insert({
    collection_name: "product_catalog", 
    data: entities
});
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("product_catalog").
    WithInt64Column("product_id", []int64{1}).
    WithFloatVectorColumn("vector", 5, [][]float32{
        {0.1, 0.2, 0.3, 0.4, 0.5},
    }).WithColumns(
    column.NewColumnJSONBytes("metadata", [][]byte{
        []byte(`{
            "category": "electronics",
            "brand": "BrandA",
            "in_stock": True,
            "price": 99.99,
            "string_price": "99.99",
            "tags": ["clearance", "summer_sale"],
            "supplier": {
                "name": "SupplierX",
                "country": "USA",
                "contact": {
                    "email": "support@supplierx.com",
                    "phone": "+1-800-555-0199"
                }
            }
        }`),
    }),
))
if err != nil {
    return err
}
# restful
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"

export entities='[
  {
    "product_id": 1,
    "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
    "metadata": {
      "category": "electronics",
      "brand": "BrandA",
      "in_stock": true,
      "price": 99.99,
      "string_price": "99.99",
      "tags": ["clearance", "summer_sale"],
      "supplier": {
        "name": "SupplierX",
        "country": "USA",
        "contact": {
          "email": "support@supplierx.com",
          "phone": "+1-800-555-0199"
        }
      }
    }
  }
]'

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/product_catalog/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
  \"data\": $entities
}"

Indexer les valeurs à l'intérieur du champ JSON

Pour accélérer le filtrage scalaire sur les champs JSON, Milvus prend en charge les types d'index suivants :

  • Index de chemin JSON - indexe des chemins JSON spécifiques avec un type de scalaire déclaré.

  • Index plat JSON - indexe un objet JSON entier (ou un sous-arbre) avec inférence automatique du type.

L'indexation des champs JSON est facultative. Il est toujours possible d'interroger ou de filtrer les chemins JSON sans index, mais les performances risquent d'être réduites en raison d'une recherche par force brute.

Choisissez entre l'index de chemin et l'index platCompatible with Milvus 2.6.x

Capacité

Index de chemin JSON

Index plat JSON

Ce qu'il indexe

Le(s) chemin(s) spécifique(s) que vous avez nommé(s)

Tous les chemins aplatis sous un chemin d'objet

Gestion des types

Vous déclarez json_cast_type (types scalaires)

Doit être JSON (inférence de type automatique)

Tableaux en tant que LHS¹

Pris en charge

Non supporté

Vitesse d'interrogation

Élevée sur les chemins indexés

Élevée, légèrement inférieure en moyenne

Utilisation du disque

Plus faible

Plus élevée

¹ Tableaux en tant que LHS signifie que le côté gauche de l'expression du filtre est un tableau JSON, par exemple :

metadata["tags"] == ["clearance", "summer_sale"]
json_contains(metadata["tags"], "clearance")

Dans ces cas, metadata["tags"] est un tableau. L'indexation plate JSON n'accélère pas de tels filtres - utilisez plutôt un index de chemin JSON avec un type de cast de tableau.

Utilisez l'index de chemin JSON lorsque :

  • Vous connaissez à l'avance les raccourcis clavier à interroger.

  • Vous devez filtrer lorsque le côté gauche est un tableau.

  • Vous voulez minimiser l'utilisation du disque.

Utilisez l'index plat JSON lorsque :

  • Vous voulez indexer un sous-arbre entier (y compris la racine).

  • Votre structure JSON change fréquemment.

  • Vous souhaitez élargir la couverture des requêtes sans avoir à déclarer chaque chemin.

Indexation des chemins JSON

Pour créer un index de chemin JSON, spécifiez :

  • JSON path (json_path) : Le chemin d'accès à la clé ou au champ imbriqué de votre objet JSON que vous souhaitez indexer.

    • Exemple :

      • Pour une clé, metadata["category"]

      • Pour un champ imbriqué, metadata["contact"]["email"]

      Ceci définit l'endroit où le moteur d'indexation doit regarder à l'intérieur de la structure JSON.

  • JSON cast type (json_cast_type) : Le type de données que Milvus doit utiliser lors de l'interprétation et de l'indexation de la valeur au niveau du chemin spécifié.

    • Ce type doit correspondre au type de données réel du champ indexé. Si vous souhaitez convertir le type de données en un autre type lors de l'indexation, envisagez d'utiliser une fonction de conversion.

    • Pour une liste complète, voir ci-dessous.

Types de cast JSON pris en charge

Les types de cast ne sont pas sensibles à la casse. Les types suivants sont pris en charge :

Type de fonte

Description

Exemple de valeur JSON

bool

Valeur booléenne

true, false

double

Valeur numérique (entier ou flottant)

42, 99.99, -15.5

varchar

Valeur de chaîne

"electronics", "BrandA"

array_bool

Tableau de booléens

[true, false, true]

array_double

Tableau de nombres

[1.2, 3.14, 42]

array_varchar

Tableau de chaînes de caractères

["tag1", "tag2", "tag3"]

Les tableaux doivent contenir des éléments du même type pour une indexation optimale. Pour plus d'informations, voir Champ de tableau.

Exemple : Créer des index de chemin JSON

En utilisant la structure JSON metadata de notre introduction, voici des exemples de création d'index sur différents chemins JSON :

# Index the category field as a string
index_params = client.prepare_index_params()

index_params.add_index(
    field_name="metadata",
    index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
    index_name="category_index",  # Unique index name
    params={
        "json_path": "metadata[\"category\"]", # Path to the JSON key to be indexed
        "json_cast_type": "varchar" # Data cast type
    }
)

# Index the tags array as string array
index_params.add_index(
    field_name="metadata",
    index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
    index_name="tags_array_index", # Unique index name
    params={
        "json_path": "metadata[\"tags\"]", # Path to the JSON key to be indexed
        "json_cast_type": "array_varchar" # Data cast type
    }
)
import io.milvus.v2.common.IndexParam;

Map<String,Object> extraParams1 = new HashMap<>();
extraParams1.put("json_path", "metadata[\"category\"]");
extraParams1.put("json_cast_type", "varchar");
indexParams.add(IndexParam.builder()
        .fieldName("metadata")
        .indexName("category_index")
        .indexType(IndexParam.IndexType.AUTOINDEX)
        .extraParams(extraParams1)
        .build());

Map<String,Object> extraParams2 = new HashMap<>();
extraParams2.put("json_path", "metadata[\"tags\"]");
extraParams2.put("json_cast_type", "array_varchar");
indexParams.add(IndexParam.builder()
        .fieldName("metadata")
        .indexName("tags_array_index")
        .indexType(IndexParam.IndexType.AUTOINDEX)
        .extraParams(extraParams2)
        .build());
const indexParams = [
  {
    collection_name: "product_catalog",
    field_name: "metadata",
    index_name: "category_index",
    index_type: "AUTOINDEX", // Can also use "INVERTED" for JSON path indexing
    extra_params: {
      json_path: 'metadata["category"]',
      json_cast_type: "varchar",
    },
  },
  {
    collection_name: "product_catalog",
    field_name: "metadata",
    index_name: "tags_array_index",
    index_type: "AUTOINDEX", // Can also use "INVERTED" for JSON path indexing
    extra_params: {
      json_path: 'metadata["tags"]',
      json_cast_type: "array_varchar",
    },
  },
];

import (
    "github.com/milvus-io/milvus/client/v2/index"
)

jsonIndex1 := index.NewJSONPathIndex(index.AUTOINDEX, "varchar", `metadata["category"]`)
    .WithIndexName("category_index")
jsonIndex2 := index.NewJSONPathIndex(index.AUTOINDEX, "array_varchar", `metadata["tags"]`)
    .WithIndexName("tags_array_index")

indexOpt1 := milvusclient.NewCreateIndexOption("product_catalog", "metadata", jsonIndex1)
indexOpt2 := milvusclient.NewCreateIndexOption("product_catalog", "metadata", jsonIndex2)
# restful
export categoryIndex='{
  "fieldName": "metadata",
  "indexName": "category_index",
  "params": {
    "index_type": "AUTOINDEX",
    "json_path": "metadata[\\\"category\\\"]",
    "json_cast_type": "varchar"
  }
}'

export tagsArrayIndex='{
  "fieldName": "metadata",
  "indexName": "tags_array_index",
  "params": {
    "index_type": "AUTOINDEX",
    "json_path": "metadata[\\\"tags\\\"]",
    "json_cast_type": "array_varchar"
  }
}'

Utiliser les fonctions JSON cast pour la conversion de typeCompatible with Milvus 2.5.14+

Si votre clé de champ JSON contient des valeurs dans un format incorrect (par exemple, des nombres stockés sous forme de chaînes), vous pouvez utiliser des fonctions cast pour convertir les valeurs lors de l'indexation.

Fonctions de conversion prises en charge

Les fonctions de conversion ne sont pas sensibles à la casse. Les types suivants sont pris en charge :

Fonction de conversion

Convertit de → en

Cas d'utilisation

"STRING_TO_DOUBLE"

Chaîne → Numérique (double)

Convertir "99.99" en 99.99

Exemple : Convertir une chaîne de chiffres en double
# Convert string numbers to double for indexing
index_params.add_index(
    field_name="metadata",
    index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
    index_name="string_to_double_index", # Unique index name
    params={
        "json_path": "metadata[\"string_price\"]", # Path to the JSON key to be indexed
        "json_cast_type": "double", # Data cast type
        "json_cast_function": "STRING_TO_DOUBLE" # Cast function; case insensitive
    }
)
Map<String,Object> extraParams3 = new HashMap<>();
extraParams3.put("json_path", "metadata[\"string_price\"]");
extraParams3.put("json_cast_type", "double");
extraParams3.put("json_cast_function", "STRING_TO_DOUBLE");
indexParams.add(IndexParam.builder()
        .fieldName("metadata")
        .indexName("string_to_double_index")
        .indexType(IndexParam.IndexType.AUTOINDEX)
        .extraParams(extraParams3)
        .build());
indexParams.push({
  collection_name: "product_catalog",
  field_name: "metadata",
  index_name: "string_to_double_index",
  index_type: "AUTOINDEX", // Can also use "INVERTED"
  extra_params: {
    json_path: 'metadata["string_price"]',
    json_cast_type: "double",
    json_cast_function: "STRING_TO_DOUBLE", // Case insensitive
  },
});

jsonIndex3 := index.NewJSONPathIndex(index.AUTOINDEX, "double", `metadata["string_price"]`)
                    .WithIndexName("string_to_double_index")

indexOpt3 := milvusclient.NewCreateIndexOption("product_catalog", "metadata", jsonIndex3)

# restful
export stringToDoubleIndex='{
  "fieldName": "metadata",
  "indexName": "string_to_double_index",
  "params": {
    "index_type": "AUTOINDEX",
    "json_path": "metadata[\\\"string_price\\\"]",
    "json_cast_type": "double",
    "json_cast_function": "STRING_TO_DOUBLE"
  }
}'
  • Le paramètre json_cast_type est obligatoire et doit être identique au type de sortie de la fonction de conversion.

  • Si la conversion échoue (par exemple, une chaîne non numérique), la valeur est ignorée et n'est pas indexée.

Indexation plate JSONCompatible with Milvus 2.6.x

Pour l'indexation plate JSON, Milvus indexe toutes les paires clé-valeur dans un chemin d'accès d'objet JSON (y compris les objets imbriqués) en aplatissant la structure JSON et en déduisant automatiquement le type de chaque valeur.

Fonctionnement de l'aplatissement et de l'inférence de type

Lorsque vous créez un index plat JSON sur un chemin d'objets, Milvus procède à

  1. Aplatir - Parcourir récursivement l'objet à partir de l'adresse json_path spécifiée et extraire les paires clé-valeur imbriquées sous forme de chemins d'accès entièrement qualifiés. En utilisant l'exemple précédent metadata:

    "metadata": {
      "category": "electronics",
      "price": 99.99,
      "supplier": { "country": "USA" }
    }
    

    devient :

    metadata["category"] = "electronics"
    metadata["price"] = 99.99
    metadata["supplier"]["country"] = "USA"
    
  2. Déduire automatiquement les types - Pour chaque valeur, Milvus détermine son type dans l'ordre suivant :

    unsigned integer → signed integer → floating-point → string
    

    Le premier type qui correspond à la valeur est utilisé pour l'indexation.

    Cela signifie que le type déduit sera toujours l'un de ces quatre.

    L'inférence de type est effectuée par document, de sorte que le même chemin peut avoir des types inférés différents d'un document à l'autre.

    Après l'inférence de type, les données aplaties sont représentées en interne sous forme de termes avec leurs types inférés, par exemple :

    ("category", Text, "electronics")
    ("price", Double, 99.99)
    ("supplier.country", Text, "USA")
    

Exemple : Créer un index plat JSON

# 1. Create a flat index on the root object of the JSON column (covers the entire JSON subtree)
index_params.add_index(
    field_name="metadata",
    index_type="AUTOINDEX",          # Or "INVERTED", same as Path Index
    index_name="metadata_flat",      # Unique index name
    params={
        "json_path": 'metadata',     # Object path: the root object of the column
        "json_cast_type": "JSON"     # Key difference: must be "JSON" for Flat Index; case-insensitive
    }
)

# 2. Optionally, create a flat index on a sub-object (e.g., supplier subtree)
index_params.add_index(
    field_name="metadata",
    index_type="AUTOINDEX",
    index_name="metadata_supplier_flat",
    params={
        "json_path": 'metadata["supplier"]',  # Object path: sub-object path
        "json_cast_type": "JSON"
    }
)
// java
// nodejs
// go
# restful

Appliquer des index à la collection

Après avoir défini les paramètres de l'index, vous pouvez les appliquer à la collection à l'aide de create_index():

client.create_index(
    collection_name="product_catalog",
    index_params=index_params
)
import io.milvus.v2.service.index.request.CreateIndexReq;

client.createIndex(CreateIndexReq.builder()
        .collectionName("product_catalog")
        .indexParams(indexParams)
        .build());
await client.createIndex(indexParams)
indexTask1, err := client.CreateIndex(ctx, indexOpt1)
if err != nil {
    return err
}
indexTask2, err := client.CreateIndex(ctx, indexOpt2)
if err != nil {
    return err
}
indexTask3, err := client.CreateIndex(ctx, indexOpt3)
if err != nil {
    return err
}
# restful
export indexParams="[
  $categoryIndex,
  $tagsArrayIndex,
  $stringToDoubleIndex
]"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
  \"collectionName\": \"product_catalog\",
  \"indexParams\": $indexParams
}"

Filtrer sur les valeurs des champs JSON

Après avoir inséré et indexé les champs JSON, vous pouvez les filtrer à l'aide d'expressions de filtrage standard avec la syntaxe du chemin JSON.

Par exemple, vous pouvez filtrer les valeurs des champs JSON :

filter = 'metadata["category"] == "electronics"'
filter = 'metadata["price"] > 50'
filter = 'json_contains(metadata["tags"], "featured")'
String filter = 'metadata["category"] == "electronics"';
String filter = 'metadata["price"] > 50';
String filter = 'json_contains(metadata["tags"], "featured")';
let filter = 'metadata["category"] == "electronics"'
let filter = 'metadata["price"] > 50'
let filter = 'json_contains(metadata["tags"], "featured")'
filter := 'metadata["category"] == "electronics"'
filter := 'metadata["price"] > 50'
filter := 'json_contains(metadata["tags"], "featured")'
# restful
export filterCategory='metadata["category"] == "electronics"'
export filterPrice='metadata["price"] > 50'
export filterTags='json_contains(metadata["tags"], "featured")'

Pour utiliser ces expressions dans une recherche ou une requête, assurez-vous que

  • Vous avez créé un index sur chaque champ vectoriel.

  • La collection est chargée en mémoire.

Pour obtenir la liste complète des opérateurs et expressions pris en charge, reportez-vous à Opérateurs JSON.

Rassembler tous les éléments

Vous avez maintenant appris à définir, insérer et éventuellement indexer des valeurs structurées à l'intérieur d'un champ JSON.

Pour compléter le flux de travail dans une application réelle, vous devrez également :

FAQ

Quelles sont les différences entre un champ JSON et un champ dynamique ?

  • Lechamp JSON est défini par le schéma. Vous devez déclarer explicitement le champ dans le schéma.

  • Lechamp dynamique est un objet JSON caché ($meta) qui stocke automatiquement tout champ non défini dans le schéma.

Les deux types de champs prennent en charge les structures imbriquées et l'indexation des chemins JSON, mais les champs dynamiques conviennent mieux aux structures de données facultatives ou évolutives.

Pour plus de détails, voir Champ dynamique.

Y a-t-il des limites à la taille d'un champ JSON ?

Oui. Chaque champ JSON est limité à 65 536 octets.

Un champ JSON permet-il de définir une valeur par défaut ?

Non, les champs JSON ne prennent pas en charge les valeurs par défaut. Toutefois, vous pouvez définir nullable=True lors de la définition du champ afin d'autoriser les entrées vides.

Pour plus d'informations, reportez-vous à la section Nullable & Default.

Existe-t-il des conventions de dénomination pour les clés des champs JSON ?

Oui, pour assurer la compatibilité avec les requêtes et l'indexation :

  • Utilisez uniquement des lettres, des chiffres et des traits de soulignement dans les clés JSON.

  • Évitez d'utiliser des caractères spéciaux, des espaces ou des points (., /, etc.).

  • Les clés incompatibles peuvent entraîner des problèmes d'analyse dans les expressions de filtre.

Comment Milvus gère-t-il les valeurs de chaîne dans les champs JSON ?

Milvus stocke les valeurs de chaîne exactement comme elles apparaissent dans l'entrée JSON, sans transformation sémantique. Les chaînes mal citées peuvent entraîner des erreurs lors de l'analyse.

Exemples de chaînes valides:

"a\"b", "a'b", "a\\b"

Exemples de chaînes non valides:

'a"b', 'a\'b'

Quelle logique de filtrage Milvus utilise-t-il pour les chemins JSON indexés ?

  • Indexation numérique:

    Si un index est créé avec json_cast_type="double", seules les conditions de filtrage numériques (par exemple, >, <, == 42) tireront parti de l'index. Les conditions non numériques peuvent revenir à un balayage par force brute.

  • Indexation des chaînes de caractères:

    Si un index utilise json_cast_type="varchar", seules les conditions de filtrage de chaînes de caractères bénéficieront de l'index ; les autres types de conditions risquent d'aboutir à une analyse par force brute.

  • Indexation booléenne:

    L'indexation booléenne se comporte de la même manière que l'indexation de chaînes de caractères, l'index n'étant utilisé que lorsque la condition correspond strictement à vrai ou faux.

Qu'en est-il de la précision numérique lors de l'indexation des champs JSON ?

Milvus stocke toutes les valeurs numériques indexées sous forme de doubles.

Si une valeur numérique dépasse 2^53, elle peut perdre en précision. Cette perte de précision peut avoir pour conséquence que les requêtes de filtrage ne correspondent pas exactement aux valeurs hors plage.

Puis-je créer plusieurs index sur le même chemin JSON avec différents types de cast ?

Non, chaque chemin JSON ne prend en charge qu'un seul index. Vous devez choisir un seul json_cast_type qui correspond à vos données. La création de plusieurs index sur le même chemin avec des types de distribution différents n'est pas prise en charge.

Que se passe-t-il si les valeurs d'un chemin JSON ont des types incohérents ?

Les types incohérents entre les entités peuvent entraîner une indexation partielle. Par exemple, si metadata["price"] est stocké à la fois sous la forme d'un nombre (99.99) et d'une chaîne de caractères ("99.99"), et que l'index est défini avec json_cast_type="double", seules les valeurs numériques seront indexées. Les entrées sous forme de chaîne de caractères seront ignorées et n'apparaîtront pas dans les résultats du filtre.

Puis-je utiliser des filtres d'un type différent de celui de la distribution indexée ?

Si l'expression de votre filtre utilise un type différent de celui de l'index json_cast_type, le système n'utilisera pas l'index et pourra revenir à un balayage brut plus lent, si les données le permettent. Pour des performances optimales, alignez toujours votre expression de filtrage sur le type de distribution de l'index.