• Informazioni su Milvus
  • Iniziare
  • Concetti
  • Guida per l'utente
  • Importazione dei dati
  • Strumenti AI
  • Guida all'amministrazione
  • Strumenti
  • Integrazioni
  • Tutorial
  • Domande frequenti
  • API Reference

Campo JSON

Milvus consente di memorizzare e indicizzare i dati strutturati all'interno di un singolo campo utilizzando il tipo di dati JSON. Questo permette di creare schemi flessibili con attributi annidati, consentendo al contempo un filtraggio efficiente tramite l'indicizzazione JSON.

Che cos'è un campo JSON?

Un campo JSON è un campo definito dallo schema di Milvus che memorizza dati strutturati a valore-chiave. I valori possono includere stringhe, numeri, booleani, array o oggetti profondamente annidati.

Ecco un esempio di come potrebbe apparire un campo JSON in un documento:

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

In questo esempio:

  • metadata è il campo JSON definito nello schema.

  • È possibile memorizzare valori piatti (ad esempio, category, in_stock), array (tags) e oggetti annidati (supplier).

Definire un campo JSON nello schema

Per utilizzare un campo JSON, occorre definirlo esplicitamente nello schema della collezione, specificando DataType come JSON.

L'esempio seguente crea una collezione con il suo schema contenente questi campi:

  • La chiave primaria (product_id)

  • Un campo vector (obbligatorio per ogni raccolta)

  • Un campo metadata di tipo JSON, che può memorizzare dati strutturati come valori piatti, array o oggetti annidati.

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" \
--header "Request-Timeout: 10" \
--data "{
  \"collectionName\": \"product_catalog\",
  \"schema\": $schema
}"

Si può anche attivare la funzione di campo dinamico per memorizzare campi non dichiarati in modo flessibile, ma non è necessaria per il funzionamento dei campi JSON. Per ulteriori informazioni, consultare Campo dinamico.

Inserire entità con dati JSON

Una volta creata la collezione, inserire le entità che contengono oggetti JSON strutturati nel campo metadata JSON.

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" \
--header "Request-Timeout: 10" \
--data "{
  \"data\": $entities
}"

Indicizzare i valori all'interno del campo JSON

Per accelerare il filtraggio scalare sui campi JSON, Milvus supporta i seguenti tipi di indici:

  • JSON path index - indicizza percorsi JSON specifici con un tipo di scalare dichiarato.

  • JSON flat index - indicizza un intero oggetto JSON (o un sottoalbero) con inferenza automatica del tipo.

L'indicizzazione dei campi JSON è facoltativa. È comunque possibile eseguire interrogazioni o filtri in base ai percorsi JSON senza un indice, ma ciò può comportare un rallentamento delle prestazioni a causa di una ricerca brutale.

Scegliere tra indice di percorso e indice piattoCompatible with Milvus 2.6.x

Capacità

Indice di percorso JSON

Indice piatto JSON

Cosa indicizza

Percorsi specifici nominati dall'utente

Tutti i percorsi appiattiti sotto un percorso oggetto

Gestione dei tipi

Si dichiara json_cast_type (tipi scalari)

Deve essere JSON (inferenza automatica del tipo)

Array come LHS¹

Supportato

Non supportato

Velocità di interrogazione

Alta su percorsi indicizzati

Alta, leggermente inferiore in media

Utilizzo del disco

Più basso

Più alto

¹ Array come LHS significa che il lato sinistro dell'espressione del filtro è un array JSON, ad esempio:

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

In questi casi, metadata["tags"] è un array. L'indicizzazione piatta di JSON non accelera tali filtri; utilizzare invece un indice di percorso JSON con un tipo di cast di array.

Utilizzare l'indice di percorso JSON quando:

  • Si conoscono in anticipo i tasti di scelta rapida da interrogare.

  • È necessario filtrare quando il lato sinistro è un array.

  • Si vuole ridurre al minimo l'uso del disco.

Usare l'indice piatto JSON quando:

  • Si vuole indicizzare un intero sottoalbero (compresa la radice).

  • La struttura JSON cambia frequentemente.

  • Si desidera una copertura di query più ampia senza dichiarare ogni percorso.

Indicizzazione dei percorsi JSON

Per creare un indice di percorsi JSON, specificare:

  • Percorso JSON (json_path): Il percorso della chiave o del campo annidato all'interno dell'oggetto JSON che si desidera indicizzare.

    • Esempio:

      • Per una chiave, metadata["category"]

      • Per un campo annidato, metadata["contact"]["email"]

      Definisce dove il motore di indicizzazione deve cercare all'interno della struttura JSON.

  • Tipo di cast JSON (json_cast_type): Il tipo di dati che Milvus deve utilizzare per interpretare e indicizzare il valore nel percorso specificato.

    • Questo tipo deve corrispondere al tipo di dati effettivo del campo da indicizzare. Se si desidera convertire il tipo di dati in un altro durante l'indicizzazione, si può utilizzare una funzione cast.

    • Per un elenco completo, vedere di seguito.

Tipi di cast JSON supportati

I tipi di cast non fanno distinzione tra maiuscole e minuscole. Sono supportati i seguenti tipi:

Tipo di cast

Descrizione

Esempio di valore JSON

bool

Valore booleano

true, false

double

Valore numerico (intero o float)

42, 99.99, -15.5

varchar

Valore stringa

"electronics", "BrandA"

array_bool

Array di booleani

[true, false, true]

array_double

Matrice di numeri

[1.2, 3.14, 42]

array_varchar

Array di stringhe

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

Gli array devono contenere elementi dello stesso tipo per un'indicizzazione ottimale. Per ulteriori informazioni, consultare Campo di array.

Esempio: Creare indici di percorsi JSON

Utilizzando la struttura JSON metadata della nostra introduzione, ecco alcuni esempi di come creare indici su diversi percorsi 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"
  }
}'

Utilizzare le funzioni di cast JSON per la conversione dei tipiCompatible with Milvus 2.5.14+

Se la chiave del campo JSON contiene valori in un formato non corretto (ad esempio, numeri memorizzati come stringhe), è possibile utilizzare le funzioni di cast per convertire i valori durante l'indicizzazione.

Funzioni cast supportate

Le funzioni cast non fanno distinzione tra maiuscole e minuscole. Sono supportati i seguenti tipi:

Funzione di fusione

Converte da → a

Caso d'uso

"STRING_TO_DOUBLE"

Stringa → Numerico (doppio)

Convertire "99.99" in 99.99

Esempio: Conversione di numeri di stringa in numeri doppi
# 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"
  }
}'
  • Il parametro json_cast_type è obbligatorio e deve essere uguale al tipo di output della funzione di cast.

  • Se la conversione fallisce (ad esempio, stringa non numerica), il valore viene saltato e non indicizzato.

Indicizzazione piatta JSONCompatible with Milvus 2.6.x

Per l'indicizzazione piatta JSON, Milvus indicizza tutte le coppie chiave-valore all'interno di un percorso di oggetti JSON (compresi gli oggetti annidati) appiattendo la struttura JSON e deducendo automaticamente il tipo di ogni valore.

Come funzionano l'appiattimento e l'inferenza del tipo

Quando si crea un indice piatto JSON su un percorso di oggetti, Milvus:

  1. Appiattisce - Attraversa ricorsivamente l'oggetto a partire dall'indirizzo json_path ed estrae le coppie chiave-valore annidate come percorsi completamente qualificati. Utilizzando l'esempio precedente di metadata:

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

    diventa:

    metadata["category"] = "electronics"
    metadata["price"] = 99.99
    metadata["supplier"]["country"] = "USA"
    
  2. Inferire automaticamente i tipi - Per ogni valore, Milvus ne determina il tipo nel seguente ordine:

    unsigned integer → signed integer → floating-point → string
    

    Il primo tipo che si adatta al valore viene utilizzato per l'indicizzazione.

    Ciò significa che il tipo dedotto sarà sempre uno di questi quattro.

    L'inferenza del tipo viene eseguita per documento, quindi lo stesso percorso può avere tipi inferiti diversi nei vari documenti.

    Dopo l'inferenza del tipo, i dati appiattiti sono rappresentati internamente come termini con i loro tipi desunti, ad esempio:

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

Esempio: Creare un indice piatto 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

Applicare gli indici all'insieme

Dopo aver definito i parametri degli indici, è possibile applicarli alla collezione utilizzando 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" \
--header "Request-Timeout: 10" \
--data "{
  \"collectionName\": \"product_catalog\",
  \"indexParams\": $indexParams
}"

Filtrare in base ai valori dei campi JSON

Dopo aver inserito e indicizzato i campi JSON, è possibile filtrare su di essi utilizzando espressioni di filtro standard con la sintassi del percorso JSON.

Ad esempio:

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")'

Per utilizzare queste espressioni in una ricerca o in una query, assicurarsi che:

  • Sia stato creato un indice su ogni campo vettoriale.

  • L'insieme sia caricato in memoria.

Per un elenco completo degli operatori e delle espressioni supportate, consultare la sezione Operatori JSON.

Mettere insieme tutto

A questo punto si è imparato a definire, inserire e, facoltativamente, indicizzare valori strutturati all'interno di un campo JSON.

Per completare il flusso di lavoro in un'applicazione reale, è necessario anche:

DOMANDE FREQUENTI

Quali sono le differenze tra un campo JSON e un campo dinamico?

  • Ilcampo JSON è definito dallo schema. È necessario dichiarare esplicitamente il campo nello schema.

  • Ilcampo dinamico è un oggetto JSON nascosto ($meta) che memorizza automaticamente qualsiasi campo non definito nello schema.

Entrambi supportano strutture annidate e l'indicizzazione dei percorsi JSON, ma i campi dinamici sono più adatti a strutture di dati opzionali o in evoluzione.

Per maggiori dettagli, consultare Campo dinamico.

Ci sono limitazioni sulla dimensione di un campo JSON?

Sì. Ogni campo JSON è limitato a 65.536 byte.

Un campo JSON supporta l'impostazione di un valore predefinito?

No, i campi JSON non supportano valori predefiniti. Tuttavia, è possibile impostare nullable=True quando si definisce il campo per consentire l'inserimento di voci vuote.

Fare riferimento a Nullable e Default per i dettagli.

Esistono convenzioni di denominazione per le chiavi dei campi JSON?

Sì, per garantire la compatibilità con le query e l'indicizzazione:

  • Utilizzare solo lettere, numeri e trattini bassi nelle chiavi JSON.

  • Evitare l'uso di caratteri speciali, spazi o punti (., /, ecc.).

  • Le chiavi incompatibili possono causare problemi di parsing nelle espressioni dei filtri.

Come gestisce Milvus i valori stringa nei campi JSON?

Milvus memorizza i valori stringa esattamente come appaiono nell'input JSON, senza alcuna trasformazione semantica. Le stringhe non correttamente virgolettate possono causare errori durante l'analisi.

Esempi di stringhe valide:

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

Esempi di stringhe non valide:

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

Quale logica di filtraggio utilizza Milvus per i percorsi JSON indicizzati?

  • Indicizzazione numerica:

    Se un indice viene creato con json_cast_type="double", solo le condizioni di filtro numeriche (ad esempio, >, <, == 42) sfrutteranno l'indice. Le condizioni non numeriche possono essere utilizzate per una scansione brutale.

  • Indicizzazione delle stringhe:

    Se un indice utilizza json_cast_type="varchar", solo le condizioni di filtro stringa trarranno vantaggio dall'indice; gli altri tipi possono essere sottoposti a una scansione brutale.

  • Indicizzazione booleana:

    L'indicizzazione booleana si comporta in modo simile all'indicizzazione delle stringhe, con l'utilizzo dell'indice solo quando la condizione corrisponde rigorosamente a vero o falso.

E la precisione numerica nell'indicizzazione dei campi JSON?

Milvus memorizza tutti i valori numerici indicizzati come doppi.

Se un valore numerico supera 2^53, può perdere precisione. Questa perdita di precisione può far sì che le query di filtro non corrispondano esattamente ai valori fuori range.

È possibile creare più indici sullo stesso percorso JSON con tipi di cast diversi?

No, ogni percorso JSON supporta un solo indice. È necessario scegliere un singolo json_cast_type che corrisponda ai dati. La creazione di più indici sullo stesso percorso con tipi di cast diversi non è supportata.

Cosa succede se i valori di un percorso JSON hanno tipi incoerenti?

I tipi incoerenti tra le entità possono portare a un'indicizzazione parziale. Ad esempio, se metadata["price"] è memorizzato sia come numero (99.99) che come stringa ("99.99") e l'indice è definito con json_cast_type="double", solo i valori numerici saranno indicizzati. Le voci in forma di stringa verranno saltate e non appariranno nei risultati del filtro.

È possibile utilizzare filtri con un tipo diverso dal tipo di cast indicizzato?

Se l'espressione del filtro utilizza un tipo diverso da quello dell'indice json_cast_type, il sistema non utilizzerà l'indice e potrà passare a una scansione bruta più lenta, se i dati lo consentono. Per ottenere prestazioni ottimali, allineare sempre l'espressione del filtro al tipo di cast dell'indice.