Campo JSON
Milvus permite-lhe armazenar e indexar dados estruturados num único campo utilizando o tipo de dados JSON. Isto permite esquemas flexíveis com atributos aninhados, permitindo ainda uma filtragem eficiente através da indexação JSON.
O que é um campo JSON?
Um campo JSON é um campo definido por um esquema no Milvus que armazena dados estruturados de valor-chave. Os valores podem incluir cadeias de caracteres, números, booleanos, matrizes ou objectos profundamente aninhados.
Aqui está um exemplo do que um campo JSON pode parecer num 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"
}
}
}
}
Neste exemplo:
metadataé o campo JSON definido no esquema.É possível armazenar valores simples (por exemplo,
category,in_stock), matrizes (tags) e objectos aninhados (supplier).
Definir um campo JSON no esquema
Para utilizar um campo JSON, defina-o explicitamente no esquema da coleção, especificando DataType como JSON.
O exemplo abaixo cria uma coleção com o respetivo esquema que contém estes campos:
A chave primária (
product_id)Um campo
vector(obrigatório para cada coleção)Um campo
metadatado tipoJSON, que pode armazenar dados estruturados como valores planos, matrizes ou objectos aninhados
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
}"
Também pode ativar a funcionalidade de campo dinâmico para armazenar campos não declarados de forma flexível, mas não é necessário para que os campos JSON funcionem. Para obter mais informações, consulte Campo dinâmico.
Inserir entidades com dados JSON
Depois que a coleção for criada, insira entidades que contenham objetos JSON estruturados no 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" \
--data "{
\"data\": $entities
}"
Indexar valores dentro do campo JSON
Para acelerar a filtragem escalar em campos JSON, o Milvus suporta os seguintes tipos de índices:
Índice de caminho JSON - indexa caminhos JSON específicos com um tipo escalar declarado.
Índice plano JSON - indexa um objeto JSON inteiro (ou subárvore) com inferência automática de tipo.
A indexação de campos JSON é opcional. Você ainda pode consultar ou filtrar por caminhos JSON sem um índice, mas isso pode resultar em um desempenho mais lento devido à pesquisa de força bruta.
Escolha entre índice de caminho e índice planoCompatible with Milvus 2.6.x
Capacidade |
Índice de caminho JSON |
Índice plano JSON |
|---|---|---|
O que ele indexa |
Caminho(s) específico(s) que nomeia |
Todos os caminhos achatados sob um caminho de objeto |
Tratamento de tipos |
O utilizador declara |
Deve ser JSON (inferência automática de tipo) |
Matrizes como LHS¹ |
Suportado |
Não suportado |
Velocidade de consulta |
Elevada em caminhos indexados |
Elevada, ligeiramente inferior em média |
Utilização do disco |
Inferior |
Superior |
Matrizes como LHS significa que o lado esquerdo da expressão de filtro é uma matriz JSON, por exemplo:
metadata["tags"] == ["clearance", "summer_sale"]
json_contains(metadata["tags"], "clearance")
Nestes casos, metadata["tags"] é uma matriz. A indexação plana JSON não acelera esses filtros - em vez disso, utilize um índice de caminho JSON com um tipo de conversão de matriz.
Utilize o índice de caminho JSON quando:
Sabe antecipadamente as teclas de atalho a consultar.
Você precisa filtrar onde o lado esquerdo é uma matriz.
Você deseja minimizar o uso do disco.
Utilize o índice plano JSON quando:
Você deseja indexar uma subárvore inteira (incluindo a raiz).
A sua estrutura JSON muda frequentemente.
Você deseja uma cobertura de consulta mais ampla sem declarar todos os caminhos.
Indexação de caminho JSON
Para criar um índice de caminho JSON, especifique:
Caminho JSON (
json_path): O caminho para a chave ou o campo aninhado no seu objeto JSON que pretende indexar.Exemplo:
Para uma chave,
metadata["category"]Para um campo aninhado,
metadata["contact"]["email"]
Isso define onde o mecanismo de indexação deve procurar dentro da estrutura JSON.
Tipo de conversão JSON (
json_cast_type): O tipo de dados que o Milvus deve utilizar ao interpretar e indexar o valor no caminho especificado.Este tipo deve corresponder ao tipo de dados real do campo que está a ser indexado. Se pretender converter o tipo de dados para outro durante a indexação, considere a utilização de uma função cast.
Para obter uma lista completa, veja abaixo.
Tipos de conversão JSON suportados
Os tipos de conversão não diferenciam maiúsculas de minúsculas. São suportados os seguintes tipos:
Tipo de elenco |
Descrição |
Exemplo de valor JSON |
|---|---|---|
|
Valor booleano |
|
|
Valor numérico (inteiro ou flutuante) |
|
|
Valor de cadeia de caracteres |
|
|
Conjunto de booleanos |
|
|
Conjunto de números |
|
|
Matriz de cadeias de caracteres |
|
As matrizes devem conter elementos do mesmo tipo para uma indexação óptima. Para mais informações, consulte Campo de matriz.
Exemplo: Criar índices de caminho JSON
Usando a estrutura metadata JSON da nossa introdução, aqui estão exemplos de como criar índices em diferentes caminhos 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"
}
}'
Usar funções de conversão de JSON para conversão de tipoCompatible with Milvus 2.5.14+
Se a chave de campo JSON contiver valores em um formato incorreto (por exemplo, números armazenados como cadeias de caracteres), é possível usar funções de conversão para converter valores durante a indexação.
Funções de conversão suportadas
As funções de conversão não diferenciam maiúsculas de minúsculas. São suportados os seguintes tipos:
Função de conversão |
Converte de → para |
Caso de utilização |
|---|---|---|
|
String → Numérico (double) |
Converter |
Exemplo: Converter números de string para 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"
}
}'
O parâmetro
json_cast_typeé obrigatório e deve ser o mesmo que o tipo de saída da função de conversão.Se a conversão falhar (por exemplo, cadeia de caracteres não numérica), o valor é ignorado e não é indexado.
Indexação plana JSONCompatible with Milvus 2.6.x
Para indexação plana JSON, Milvus indexa todos os pares chave-valor dentro de um caminho de objeto JSON (incluindo objetos aninhados) achatando a estrutura JSON e inferindo automaticamente o tipo de cada valor.
Como o achatamento e a inferência de tipo funcionam
Quando você cria um índice plano JSON em um caminho de objeto, Milvus irá:
Achatar - Atravessar recursivamente o objeto a partir do especificado
json_pathe extrair pares de valores-chave aninhados como caminhos totalmente qualificados. Usando o exemplo anteriormetadata:"metadata": { "category": "electronics", "price": 99.99, "supplier": { "country": "USA" } }torna-se:
metadata["category"] = "electronics" metadata["price"] = 99.99 metadata["supplier"]["country"] = "USA"Inferir tipos automaticamente - Para cada valor, o Milvus determina o seu tipo pela seguinte ordem:
unsigned integer → signed integer → floating-point → stringO primeiro tipo que se encaixa no valor é usado para indexação.
Isto significa que o tipo inferido será sempre um destes quatro.
A inferência de tipo é efectuada por documento, pelo que o mesmo caminho pode ter diferentes tipos inferidos entre documentos.
Após a inferência de tipo, os dados achatados são representados internamente como termos com seus tipos inferidos, por exemplo:
("category", Text, "electronics") ("price", Double, 99.99) ("supplier.country", Text, "USA")
Exemplo: Criar índice plano 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
Aplicar índices à coleção
Depois de definir os parâmetros do índice, pode aplicá-los à coleção utilizando 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
}"
Filtrar por valores de campo JSON
Depois de inserir e indexar campos JSON, é possível filtrá-los usando expressões de filtro padrão com sintaxe de caminho JSON.
Por exemplo:
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")'
Para usar essas expressões em uma pesquisa ou consulta, certifique-se de que:
Criou um índice em cada campo de vetor.
A coleção está carregada na memória.
Para obter uma lista completa de operadores e expressões suportados, consulte Operadores JSON.
Juntar tudo
Até agora, você aprendeu como definir, inserir e opcionalmente indexar valores estruturados dentro de um campo JSON.
Para concluir o fluxo de trabalho em um aplicativo do mundo real, você também precisará:
Criar um índice nos campos de vetor (obrigatório para cada campo de vetor em uma coleção)
Consulte Definir parâmetros de índice
Carregar a coleção
Consulte Carregar e liberar
Pesquisar ou consultar usando filtros de caminho JSON
Consulte Pesquisa filtrada e operadores JSON
PERGUNTAS FREQUENTES
Quais são as diferenças entre um campo JSON e o campo dinâmico?
O campo JSON é definido pelo esquema. É necessário declarar explicitamente o campo no esquema.
O campo dinâmico é um objeto JSON oculto (
$meta) que armazena automaticamente qualquer campo não definido no esquema.
Ambos suportam estruturas aninhadas e indexação de caminhos JSON, mas os campos dinâmicos são mais adequados para estruturas de dados opcionais ou em evolução.
Consulte Campo dinâmico para obter detalhes.
Há alguma limitação no tamanho de um campo JSON?
Sim. Cada campo JSON está limitado a 65.536 bytes.
Um campo JSON suporta a definição de um valor predefinido?
Não, os campos JSON não suportam valores predefinidos. No entanto, pode definir nullable=True ao definir o campo para permitir entradas vazias.
Consulte Nullable & Default para obter detalhes.
Há alguma convenção de nomenclatura para chaves de campo JSON?
Sim, para garantir a compatibilidade com consultas e indexação:
Use apenas letras, números e sublinhados nas chaves JSON.
Evite usar caracteres especiais, espaços ou pontos (
.,/, etc.).Chaves incompatíveis podem causar problemas de análise em expressões de filtro.
Como é que o Milvus lida com valores de cadeia de caracteres em campos JSON?
Milvus armazena valores de string exatamente como eles aparecem na entrada JSON - sem transformação semântica. As cadeias de caracteres com aspas inadequadas podem resultar em erros durante a análise.
Exemplos de strings válidas:
"a\"b", "a'b", "a\\b"
Exemplos de cadeias de caracteres inválidas:
'a"b', 'a\'b'
Que lógica de filtragem o Milvus usa para caminhos JSON indexados?
Indexação numérica:
Se um índice for criado com
json_cast_type="double", apenas as condições de filtragem numéricas (por exemplo,>,<,== 42) irão alavancar o índice. As condições não numéricas podem voltar para uma varredura de força bruta.Indexação de cadeias de caracteres:
Se um índice utilizar
json_cast_type="varchar", apenas as condições de filtro de cadeias de caracteres beneficiarão do índice; outros tipos podem ser afectados por uma verificação de força bruta.Indexação booleana:
A indexação booleana comporta-se de forma semelhante à indexação de cadeias de caracteres, com a utilização do índice apenas quando a condição corresponde estritamente a verdadeiro ou falso.
E quanto à precisão numérica ao indexar campos JSON?
Milvus armazena todos os valores numéricos indexados como duplos.
Se um valor numérico exceder 2^53, pode perder a precisão. Esta perda de precisão pode fazer com que as consultas de filtragem não correspondam exatamente a valores fora do intervalo.
Posso criar vários índices no mesmo caminho JSON com diferentes tipos de elenco?
Não, cada caminho JSON suporta apenas um índice. Tem de escolher um único json_cast_type que corresponda aos seus dados. Não é suportada a criação de vários índices no mesmo caminho com diferentes tipos de elenco.
E se os valores num caminho JSON tiverem tipos inconsistentes?
Tipos inconsistentes entre entidades podem levar à indexação parcial. Por exemplo, se metadata["price"] for armazenado como um número (99.99) e uma cadeia de caracteres ("99.99"), e o índice for definido com json_cast_type="double", apenas os valores numéricos serão indexados. As entradas em forma de cadeia de caracteres serão ignoradas e não aparecerão nos resultados do filtro.
Posso utilizar filtros com um tipo diferente do tipo de elenco indexado?
Se a expressão do filtro utilizar um tipo diferente do tipo do índice json_cast_type, o sistema não utilizará o índice e poderá recorrer a uma pesquisa de força bruta mais lenta, se os dados o permitirem. Para obter o melhor desempenho, alinhe sempre a sua expressão de filtro com o tipo de conversão do índice.