Descripción general de los campos JSON
Al desarrollar aplicaciones como catálogos de productos, sistemas de gestión de contenidos o motores de preferencias de usuario, a menudo es necesario almacenar metadatos flexibles junto con las representaciones vectoriales. Los atributos de los productos varían según la categoría, las preferencias de los usuarios evolucionan con el tiempo y las propiedades de los documentos presentan estructuras anidadas complejas. Los campos JSON de Milvus resuelven este reto al permitir almacenar y consultar datos estructurados de forma flexible sin sacrificar el rendimiento.
¿Qué es un campo JSON?
Un campo JSON es un tipo de datos definido por un esquema (DataType.JSON) en Milvus que almacena datos estructurados de tipo clave-valor. A diferencia de las columnas rígidas de las bases de datos tradicionales, los campos JSON admiten objetos anidados, matrices y tipos de datos mixtos, al tiempo que ofrecen múltiples opciones de indexación para realizar consultas rápidas.
Ejemplo de estructura de un 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"
}
}
}
}
En este ejemplo, metadata es un único campo JSON que contiene una mezcla de valores planos (p. ej., category, in_stock), matrices (tags) y objetos anidados (supplier).
Convención de nomenclatura: utiliza únicamente letras, números y guiones bajos en las claves JSON. Evita los caracteres especiales, los espacios o los puntos, ya que pueden provocar problemas de análisis en las consultas.
Campo JSON frente a campo dinámico
Un punto habitual de confusión es la diferencia entre un campo JSON y el campo dinámico. Aunque ambos están relacionados con JSON, tienen finalidades distintas.
La siguiente tabla resume las diferencias clave entre un campo JSON y un campo dinámico:
Característica |
Campo JSON |
Campo dinámico |
|---|---|---|
Definición del esquema |
Un campo escalar que debe declararse explícitamente en el esquema de la colección con el tipo |
Un campo JSON oculto (denominado « |
Caso de uso |
Almacena datos estructurados cuyo esquema es conocido y coherente. |
Almacena datos flexibles, en evolución o semiestructurados que no se ajustan a un esquema fijo. |
Control |
Tú controlas el nombre y la estructura del campo. |
Gestión por parte del sistema para los campos no definidos. |
Consultas |
Realiza consultas utilizando el nombre del campo o la clave de destino dentro del campo JSON: |
Realiza la consulta directamente utilizando la clave del campo dinámico: |
Operaciones básicas
El flujo de trabajo básico para utilizar un campo JSON consiste en definirlo en su esquema, insertar datos y, a continuación, consultar los datos mediante expresiones de filtro específicas.
Definir un campo JSON
Para utilizar un campo JSON, defínelo explícitamente en el esquema de la colección al crearla. El siguiente ejemplo muestra cómo crear una colección con un campo metadata de 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
)
En este ejemplo, el campo JSON definido en el esquema de la colección permite valores nulos con nullable=True. Para obtener más información, consulta «Nullable y por defecto».
Insertar datos
Una vez creada la colección, inserta entidades que contengan objetos JSON estructurados en el campo JSON designado. Tus datos deben tener el formato de una lista de diccionarios.
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)
Operaciones de filtrado
Antes de poder realizar operaciones de filtrado en campos JSON, asegúrate de que:
Ha creado un índice en cada campo vectorial.
La colección esté cargada en memoria.
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")
Una vez cumplidos estos requisitos, puede utilizar las expresiones que se indican a continuación para filtrar su colección en función de los valores del campo JSON. Estas expresiones de filtrado utilizan una sintaxis específica de ruta JSON y operadores específicos.
Filtrado con la sintaxis de ruta JSON
Para consultar una clave específica, utiliza la notación entre corchetes para acceder a las claves JSON: json_field_name["key"]. En el caso de claves anidadas, encadenalas: json_field_name["key1"]["key2"].
Para filtrar las entidades en las que category es "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 las entidades en las que la clave anidada supplier["country"] sea "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)
Filtrado con operadores específicos de JSON
Milvus también ofrece operadores especiales para consultar valores de matriz en claves de campo JSON específicas. Por ejemplo:
json_contains(identifier, expr): Comprueba si existe un elemento o submatriz específico dentro de una matriz JSONjson_contains_all(identifier, expr): Garantiza que todos los elementos de la expresión JSON especificada estén presentes en el campojson_contains_any(identifier, expr): Filtra las entidades en las que exista al menos un miembro de la expresión JSON dentro del campo
Para encontrar un producto que tenga el valor « "summer_sale" » bajo la clave « 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 buscar un producto que tenga al menos uno de los valores « "electronics" », « "new" » o « "clearance" » bajo la clave « 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 obtener más información sobre los operadores específicos de JSON, consulta Operadores JSON.
Siguiente: Acelerar consultas JSON
De forma predeterminada, las consultas en campos JSON sin aceleración realizarán un escaneo completo de todas las filas, lo que puede resultar lento en conjuntos de datos de gran tamaño. Para acelerar las consultas JSON, Milvus ofrece funciones avanzadas de indexación y optimización del almacenamiento.
A partir de Milvus 3.0.0, la indexación JSON de objetos completos (json_cast_type="JSON"), también conocida como indexación JSON plana, ha quedado obsoleta. Los índices existentes y las nuevas solicitudes de creación de índices siguen siendo compatibles por motivos de compatibilidad, pero este modo ya no se recomienda para nuevas cargas de trabajo. Utilice la indexación de rutas JSON para rutas de consulta conocidas, o considere el «JSON Shredding» para una aceleración general de las consultas en documentos complejos o en constante evolución.
La tabla siguiente resume sus diferencias y los escenarios de uso más adecuados:
Técnica |
Ideal para |
Aceleración de matrices |
Notas |
|---|---|---|---|
Indexación JSON |
Conjunto reducido de claves a las que se accede con frecuencia, matrices en una clave de matriz específica |
Sí (en la clave de matriz indexada) |
Es necesario preseleccionar las claves; requiere mantenimiento si el esquema evoluciona |
Fragmentación de JSON |
Aumento general de la velocidad en muchas claves; flexible para consultas variadas |
No (no acelera los valores dentro de las matrices) |
Configuración de almacenamiento adicional; los arrays siguen necesitando un índice por clave |
Índice NGRAM |
Búsquedas con comodines, coincidencia de subcadenas en campos de texto |
N/A |
No apto para filtros numéricos o de rango |
Consejo: Puedes combinar estos enfoques; por ejemplo, utiliza el desglose de JSON para acelerar consultas amplias, la indexación JSON para claves de matriz de alta frecuencia y la indexación NGRAM para una búsqueda de texto flexible.
Para obtener detalles sobre la implementación, consulta:
Preguntas frecuentes
¿Existen limitaciones en cuanto al tamaño de un campo JSON?
Sí. Cada campo JSON tiene un límite de 65 536 bytes.
¿Se puede establecer un valor por defecto en un campo JSON?
No, los campos JSON no admiten valores por defecto. Sin embargo, al definir el campo puedes establecer la opció nullable=True para permitir entradas vacías.
Consulta « Nullable y por defecto » para obtener más detalles.
¿Existen convenciones de nomenclatura para las claves de los campos JSON?
Sí, para garantizar la compatibilidad con las consultas y la indexación:
Utiliza únicamente letras, números y guiones bajos en las claves JSON.
Evita el uso de caracteres especiales, espacios o puntos (
.,/, etc.).Las claves incompatibles pueden provocar problemas de análisis en las expresiones de filtro.
¿Cómo gestiona Milvus los valores de cadena en los campos JSON?
Milvus almacena los valores de cadena tal y como aparecen en la entrada JSON, sin transformación semántica. Las cadenas con comillas incorrectas pueden provocar errores durante el análisis sintáctico.
Ejemplos de cadenas válidas:
"a\"b", "a'b", "a\\b"
Ejemplos de cadenas no válidas:
'a"b', 'a\'b'