Descrição geral do campo JSON
Ao criar aplicações como catálogos de produtos, sistemas de gestão de conteúdos ou motores de preferências do utilizador, é frequentemente necessário armazenar metadados flexíveis juntamente com as suas incorporações vectoriais. Os atributos dos produtos variam por categoria, as preferências dos utilizadores evoluem ao longo do tempo e as propriedades dos documentos têm estruturas complexas aninhadas. Os campos JSON no Milvus resolvem este desafio, permitindo-lhe armazenar e consultar dados estruturados flexíveis sem sacrificar o desempenho.
O que é um campo JSON?
Um campo JSON é um tipo de dados definido pelo esquema (DataType.JSON) em Milvus que armazena dados estruturados de valor-chave. Ao contrário das colunas rígidas tradicionais de bases de dados, os campos JSON acomodam objectos aninhados, arrays e tipos de dados mistos, ao mesmo tempo que fornecem várias opções de indexação para consultas rápidas.
Exemplo de estrutura de campo JSON:
{
"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 é um único campo JSON que contém uma mistura de valores simples (por exemplo, category, in_stock), matrizes (tags) e objectos aninhados (supplier).
Convenção de nomenclatura: Utilize apenas letras, números e sublinhados nas chaves JSON. Evite caracteres especiais, espaços ou pontos, pois eles podem causar problemas de análise em consultas.
Campo JSON vs. campo dinâmico
Um ponto comum de confusão é a diferença entre um campo JSON e o campo dinâmico. Embora ambos estejam relacionados com o JSON, têm objectivos diferentes.
A tabela abaixo resume as principais diferenças entre um campo JSON e o campo dinâmico:
Caraterística |
Campo JSON |
Campo dinâmico |
|---|---|---|
Definição de esquema |
Um campo escalar que deve ser explicitamente declarado no esquema da coleção com o tipo |
Um campo JSON oculto (denominado |
Caso de utilização |
Armazena dados estruturados em que o esquema é conhecido e consistente. |
Armazena dados flexíveis, em evolução ou semi-estruturados que não se enquadram num esquema fixo. |
Controlo |
O utilizador controla o nome e a estrutura do campo. |
Gerido pelo sistema para campos indefinidos. |
Consulta |
Consulta utilizando o nome do campo ou a chave de destino dentro do campo JSON: |
Consulta direta utilizando a chave de campo dinâmica: |
Operações básicas
O fluxo de trabalho fundamental para utilizar um campo JSON envolve a sua definição no esquema, a inserção de dados e, em seguida, a consulta dos dados utilizando expressões de filtro específicas.
Definir um campo JSON
Para utilizar um campo JSON, defina-o explicitamente no esquema da coleção ao criar a coleção. O exemplo seguinte demonstra como criar uma coleção com um campo metadata do tipo DataType.JSON:
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530") # Replace with your server address
# Create schema
schema = client.create_schema(auto_id=False, enable_dynamic_field=True)
schema.add_field(field_name="product_id", datatype=DataType.INT64, is_primary=True) # Primary field
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5) # Vector field
# Define a JSON field that allows null values
schema.add_field(field_name="metadata", datatype=DataType.JSON, nullable=True)
client.create_collection(
collection_name="product_catalog",
schema=schema
)
Neste exemplo, o campo JSON definido no esquema de coleção permite valores nulos com nullable=True. Para mais informações, consulte Nullable & Default.
Inserir dados
Uma vez criada a coleção, insira entidades que contenham objectos JSON estruturados no campo JSON designado. Os seus dados devem ser formatados como uma lista de dicionários.
entities = [
{
"product_id": 1,
"vector": [0.1, 0.2, 0.3, 0.4, 0.5],
"metadata": { # JSON field
"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)
Operações de filtragem
Antes de poder efetuar operações de filtragem nos campos JSON, certifique-se de que:
Criou um índice em cada campo de vetor.
A coleção está carregada na memória.
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector",
index_type="AUTOINDEX",
index_name="vector_index",
metric_type="COSINE"
)
client.create_index(collection_name="product_catalog", index_params=index_params)
client.load_collection(collection_name="product_catalog")
Uma vez cumpridos estes requisitos, pode utilizar as expressões abaixo para filtrar a sua coleção com base nos valores do campo JSON. Essas expressões de filtro utilizam a sintaxe de caminho JSON específica e operadores dedicados.
Filtragem com sintaxe de caminho JSON
Para consultar uma chave específica, utilize a notação entre parênteses para aceder a chaves JSON: json_field_name["key"]. Para chaves aninhadas, encadeie-as: json_field_name["key1"]["key2"].
Para filtrar entidades em que category é "electronics":
# Define filter expression
filter = 'metadata["category"] == "electronics"'
client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
Para filtrar entidades em que a chave aninhada supplier["country"] é "USA":
# Define filter expression
filter = 'metadata["supplier"]["country"] == "USA"'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Filtragem com operadores específicos de JSON
Milvus também fornece operadores especiais para consultar valores de array em chaves de campo JSON específicas. Por exemplo:
json_contains(identifier, expr): Verifica se um elemento específico ou sub-array existe dentro de um array JSONjson_contains_all(identifier, expr): Assegura que todos os elementos da expressão JSON especificada estão presentes no campojson_contains_any(identifier, expr): Filtra entidades em que pelo menos um membro da expressão JSON existe no campo
Para encontrar um produto que tenha o valor "summer_sale" sob a chave tags:
# Define filter expression
filter = 'json_contains(metadata["tags"], "summer_sale")'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Para encontrar um produto que tenha pelo menos um dos valores "electronics", "new", ou "clearance" sob a chave tags:
# Define filter expression
filter = 'json_contains_any(metadata["tags"], ["electronics", "new", "clearance"])'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Para obter mais informações sobre operadores específicos de JSON, consulte Operadores JSON.
Próximo: Acelerar consultas JSON
Por padrão, as consultas em campos JSON sem aceleração executarão uma varredura completa de todas as linhas, o que pode ser lento em grandes conjuntos de dados. Para acelerar as consultas JSON, o Milvus fornece recursos avançados de indexação e otimização de armazenamento.
A tabela abaixo resume as suas diferenças e os cenários de melhor utilização:
Técnica |
Melhor para |
Aceleração de matrizes |
Notas |
|---|---|---|---|
Indexação JSON |
Pequeno conjunto de chaves frequentemente acedidas, matrizes numa chave de matriz específica |
Sim (na chave do array indexado) |
Deve pré-selecionar chaves, manutenção necessária se o esquema evoluir |
Fragmentação JSON |
Aceleração geral em muitas chaves, flexível para consultas variadas |
Não (não acelera os valores dentro das matrizes) |
Configuração de armazenamento extra, as matrizes ainda precisam de um índice por chave |
Índice NGRAM |
Pesquisas curinga, correspondência de substring em campos de texto |
N/A |
Não para filtros numéricos/de intervalo |
Dica: você pode combinar essas abordagens - por exemplo, usar a fragmentação JSON para aceleração de consulta ampla, a indexação JSON para chaves de matriz de alta frequência e a indexação NGRAM para pesquisa de texto flexível.
Para obter detalhes de implementação, consulte:
PERGUNTAS FREQUENTES
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 por defeito?
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 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 strings inválidas:
'a"b', 'a\'b'