Una Entidad, Muchos Vectores: Búsqueda a Nivel de Entidad y de Elemento con StructArray de Milvus 3.0
La mayoría de los esquemas de bases de datos vectoriales parten de un supuesto simple: una entidad, una incrustación. Un producto obtiene un vector, al igual que un documento. Una consulta de usuario se incrusta y se compara con esos vectores mediante búsqueda de vecinos más cercanos aproximados (ANN). Este modelo funciona para la primera generación de casos de uso de búsqueda vectorial, incluidos RAG, búsqueda semántica y sistemas de recomendación.
Sin embargo, los datos de IA del mundo real rara vez se ajustan a ese supuesto. Un video contiene clips, tomas o fotogramas clave, cada uno con su propia incrustación, rango de tiempo, subtítulo, etiqueta de escena y puntuación de confianza. Un producto puede tener varias imágenes y ángulos de visualización. Un documento largo contiene pasajes o secciones cuyo significado local importa más que una única incrustación de todo el documento. Los populares modelos de interacción tardía exponen la misma limitación a una granularidad aún más fina: ColBERT produce un vector por token, mientras que ColPali produce un vector por parche visual.
En cada caso, la entidad principal sigue siendo la unidad que la aplicación almacena, muestra, protege y devuelve. Sin embargo, la relevancia, el filtrado y la explicación de resultados a menudo dependen de elementos dentro de esa entidad.
La nueva función StructArray le brinda a Milvus un modelo de datos nativo para esta forma: una entidad contiene un arreglo ordenado de elementos Struct definidos por el esquema, y cada elemento puede llevar metadatos escalares, incrustaciones vectoriales, o ambos. Milvus puede filtrar campos que pertenecen al mismo elemento, comparar dos listas de incrustaciones a nivel de entidad, o buscar elementos individuales y devolver el desplazamiento correspondiente.
Este artículo utiliza un ejemplo de búsqueda de videos para explicar el modelo de datos y luego lo recorre a través del diseño de esquema, el filtrado, las granularidades de búsqueda vectorial, las estrategias de índice EmbeddingList, la consolidación de resultados híbridos y el diseño físico que hace ejecutable la función.
Por qué un vector y un modelo de fila plana ya no son suficientes
Considere un usuario que busca en un catálogo de videos "una persona cortando verduras en una cocina". La señal relevante puede estar en un clip de ocho segundos, no en una incrustación de todo el video. Comprimir cada clip, objeto y acción en un solo vector puede preservar el tema general, pero puede diluir los detalles locales.
La misma discrepancia aparece en otras cargas de trabajo:
- La relevancia de un producto puede provenir de una de varias imágenes o ángulos.
- Un documento puede coincidir por un pasaje en lugar de por su tema general.
- La memoria de un agente puede contener varias observaciones, de las cuales solo una importa para la tarea actual.
- Un registro ColBERT o ColPali contiene una lista de longitud variable de vectores de token o parche en lugar de un único vector denso.
Una alternativa es dividir cada clip, imagen o pasaje en una fila de base de datos separada. Eso permite la búsqueda local, pero también separa cada fragmento de su entidad principal. Los metadatos de la entidad principal pueden repetirse en varias filas, y la recuperación a nivel de entidad requiere agrupación, deduplicación y reordenamiento después de la búsqueda de fragmentos.
El almacenamiento anidado por sí solo no resuelve el problema de consulta. JSON puede almacenar objetos, pero no le da a Milvus un esquema de subcampo predefinido para indexación vectorial y escalar. Los arreglos paralelos pueden almacenar subtítulos, etiquetas de escena y valores de confianza, pero la aplicación debe mantener la alineación de desplazamientos. La base de datos no puede inferir de manera segura que scene_type[3] y label_confidence[3] describen el mismo clip a menos que esa relación sea parte del modelo de datos.
StructArray codifica esa relación directamente. Mantiene los elementos locales dentro de la entidad principal mientras expone sus subcampos alineados a la validación de esquema, indexación, filtrado y búsqueda vectorial.
¿Qué es StructArray y su modelo de datos?
Un StructArray, también conocido como arreglo de estructuras, almacena un conjunto ordenado de elementos Struct en cada entidad. Un campo StructArray es un Array cuyos elementos siguen todos un esquema Struct predefinido. Para una colección de videos, la forma lógica podría verse así:
Plaintext
clips: ARRAY<STRUCT<
clip_embedding_list: FLOAT_VECTOR,
clip_embedding: FLOAT_VECTOR,
start_sec: DOUBLE,
end_sec: DOUBLE,
caption: VARCHAR,
scene_type: VARCHAR,
label_confidence: FLOAT
>>
Aquí:
clipses el campo StructArray principal.clip_embedding_list,clip_embedding,start_secy los demás atributos son subcampos.clips[0]es el primer clip.- Cada subcampo en el desplazamiento
0pertenece a ese mismo clip. - Cada subcampo en el desplazamiento
3pertenece a otro clip.
Los dos subcampos vectoriales sirven para diferentes modos de búsqueda. clips[clip_embedding_list] se indexa con una métrica MAX_SIM* para búsqueda EmbeddingList a nivel de entidad, mientras que clips[clip_embedding] se indexa con una métrica vectorial regular para búsqueda a nivel de elemento. Debido a que un campo vectorial o subcampo vectorial acepta solo un índice, una colección que necesite ambos modos debe definir e indexar los dos subcampos por separado.
Este modelo admite tres semánticas de consulta distintas.
1. La búsqueda EmbeddingList devuelve entidades principales
Los vectores en clips[clip_embedding_list] forman una lista de incrustaciones para el video. La consulta también es un EmbeddingList. Milvus compara la lista de consulta con cada lista almacenada usando una métrica MAX_SIM* y devuelve un resultado a nivel de entidad.
Plaintext
clips[clip_embedding_list] = [
embedding_0,
embedding_1,
embedding_2,
...
]
2. La familia MATCH_* filtra entidades principales
MATCH_ANY, MATCH_ALL, MATCH_LEAST, MATCH_MOST y MATCH_EXACT evalúan un predicado contra los elementos Struct, cuentan cuántos elementos lo satisfacen y deciden si la entidad principal pasa el filtro.
Por ejemplo:
Plaintext
MATCH_ANY(clips, $[scene_type] == "kitchen" && $[label_confidence] > 0.8)
Ambas condiciones escalares deben ser verdaderas en el mismo desplazamiento de clip. Milvus no combina una etiqueta de cocina de un clip con un valor de alta confianza de otro.
3. La búsqueda a nivel de elemento devuelve el desplazamiento del elemento coincidente
Un vector de consulta regular puede buscar en cada vector de clips[clip_embedding] de forma independiente. Cada coincidencia identifica la entidad principal y el desplazamiento basado en cero del elemento Struct coincidente. Un element_filter puede restringir qué elementos participan en esa búsqueda vectorial.
Estas operaciones comparten una premisa: Milvus sabe qué valores vectoriales y escalares pertenecen al mismo elemento, y qué elementos pertenecen a la misma entidad.
StructArray no es un sistema de anidamiento arbitrario de propósito general. Su modelo actual es un Array de elementos Struct con subcampos escalares y vectoriales compatibles. Ese límite hace manejables la indexación de subcampos y la ejecución consciente de elementos.
Construya el esquema, los índices y la ruta de inserción
El siguiente ejemplo simplificado de PyMilvus crea una colección de videos con un vector de nivel superior y un StructArray para clips. Utiliza subcampos vectoriales de clip separados para que la misma colección pueda demostrar ambos modos de búsqueda.
from pymilvus import DataType, MilvusClient
client = MilvusClient(uri=“http://localhost:19530”)
schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field(“id”, DataType.INT64, is_primary=True)
schema.add_field(“title”, DataType.VARCHAR, max_length=512)
schema.add_field(“video_embedding”, DataType.FLOAT_VECTOR, dim=768)
# Define the Struct schema explicitly.
clip_schema = client.create_struct_field_schema()
clip_schema.add_field(“clip_embedding_list”, DataType.FLOAT_VECTOR, dim=768)
clip_schema.add_field(“clip_embedding”, DataType.FLOAT_VECTOR, dim=768)
clip_schema.add_field(“start_sec”, DataType.DOUBLE)
clip_schema.add_field(“end_sec”, DataType.DOUBLE)
clip_schema.add_field(“caption”, DataType.VARCHAR, max_length=2048)
clip_schema.add_field(“scene_type”, DataType.VARCHAR, max_length=128)
clip_schema.add_field(“label_confidence”, DataType.FLOAT)
schema.add_field(
“clips”,
datatype=DataType.ARRAY,
element_type=DataType.STRUCT,
struct_schema=clip_schema,
max_capacity=1024,
)
client.create_collection(“videos”, schema=schema)
Los subcampos vectoriales deben indexarse antes de la búsqueda. Debido a que la familia de métricas determina el modo de búsqueda, cada subcampo vectorial recibe su propio índice:
index_params = client.prepare_index_params()
# EmbeddingList search.
index_params.add_index(
field_name="clips[clip_embedding_list]",
index_type=“HNSW”,
metric_type=“MAX_SIM_COSINE”,
index_name=“clips_clip_embedding_list_maxsim_idx”,
params={“M”: 16, “efConstruction”: 200},
)
# Element-level search.
index_params.add_index(
field_name="clips[clip_embedding]",
index_type=“HNSW”,
metric_type=“COSINE”,
index_name=“clips_clip_embedding_cosine_idx”,
params={“M”: 16, “efConstruction”: 200},
)
client.create_index(“videos”, index_params=index_params)
Los índices escalares son opcionales, pero los subcampos que aparecen con frecuencia en filtros a gran escala deberían usar un índice escalar compatible. Por ejemplo, clips[scene_type] puede usar un índice invertido, mientras que un subcampo numérico como clips[label_confidence] puede usar un índice adecuado para filtrado numérico.
Inserte datos en su forma natural de entidad: una fila de video con un arreglo de objetos de clip. Para mantener el ejemplo compacto, escribe el mismo vector de clip en ambos subcampos vectoriales.
rows = [
{
"id": 1,
"title": "cooking tutorial",
"video_embedding": video_vec,
"clips": [
{
"clip_embedding_list": clip_vec_1,
"clip_embedding": clip_vec_1,
"start_sec": 0.0,
"end_sec": 8.0,
"caption": "A person washes vegetables.",
"scene_type": "kitchen",
"label_confidence": 0.92,
},
{
"clip_embedding_list": clip_vec_2,
"clip_embedding": clip_vec_2,
"start_sec": 8.0,
"end_sec": 16.0,
"caption": "A person cuts carrots on a board.",
"scene_type": "kitchen",
"label_confidence": 0.96,
},
],
}
]
client.insert(“videos”, rows)
client.flush(“videos”)
client.load_collection(“videos”)
En el límite de la API, clips sigue siendo un arreglo de objetos estructurados. Dentro de Milvus, cada subcampo sigue la ruta tipada requerida para su propio índice, filtro y comportamiento de salida. Esa distinción es transparente en el momento de la inserción, pero fundamental para todo lo que sigue.
El filtrado de mismo elemento es la diferencia entre estructura y arreglos paralelos
El principal beneficio del filtrado no es una sintaxis más corta para campos anidados. Es la correlación correcta entre subcampos escalares.
Supongamos que la aplicación necesita videos que contengan un clip de cocina con confianza de etiqueta superior a 0.8. No es suficiente que un video contenga algún clip de cocina y algún clip de alta confianza; el mismo clip debe satisfacer ambas condiciones.
La familia MATCH_* de StructArray expresa esto directamente:
Plaintext
MATCH_ANY(clips, $[scene_type] == "kitchen" && $[label_confidence] > 0.8)
MATCH_ALL(clips, $[label_confidence] > 0.5)
MATCH_LEAST(clips, $[scene_type] == "sports", threshold=3)
MATCH_MOST(clips, $[label_confidence] < 0.2, threshold=1)
MATCH_EXACT(clips, $[scene_type] == "intro", threshold=1)
Milvus evalúa el predicado en cada desplazamiento de elemento y luego aplica el cuantificador del operador para decidir si la entidad principal pasa:
MATCH_ANY: Al menos un elemento coincide.MATCH_ALL: Todos los elementos coinciden.MATCH_LEAST: Al menosthresholdelementos coinciden.MATCH_MOST: Como máximothresholdelementos coinciden.MATCH_EXACT: Exactamentethresholdelementos coinciden.
Si los mismos datos se almacenaran como dos arreglos independientes, la siguiente expresión no preservaría esa correlación:
Plaintext
array_contains(clips[scene_type], "kitchen")
AND
array_contains(clips[label_confidence], 0.9)
Los dos valores podrían ocurrir en desplazamientos diferentes. Eso puede ser válido para atributos no relacionados, pero es incorrecto cuando ambas condiciones describen el mismo clip, imagen de producto o pasaje de documento.
StructArray hace que la identidad del elemento sea parte del predicado de la base de datos, en lugar de una convención que la aplicación debe imponer.
Dos granularidades de búsqueda vectorial, dos identidades de resultado
Una vez que una entidad almacena múltiples vectores, la recuperación debe resolver una cuestión de modelado antes de que comience la búsqueda ANN:
¿Deben puntuarse los vectores juntos como una representación de la entidad principal, o debe competir cada vector de elemento de forma independiente?
StructArray admite ambos modelos, pero utilizan diferentes formas de consulta, familias de métricas, subcampos vectoriales e identidades de resultado.
Búsqueda EmbeddingList: una lista de vectores de consulta encuentra una entidad
Una consulta EmbeddingList contiene múltiples vectores. Un video de consulta podría dividirse en varios clips; una consulta de producto podría contener varias imágenes de referencia; una consulta ColBERT contiene un vector por token de consulta.
Para cada entidad, Milvus compara la lista de consulta con la lista de incrustaciones almacenada de la entidad. Bajo la puntuación estilo MaxSim, cada vector de consulta selecciona su mejor coincidencia en la lista de la entidad, y Milvus agrega esas puntuaciones de mejor coincidencia en una puntuación de entidad. La coincidencia final representa la entidad principal, no un elemento Struct particular.
from pymilvus.client.embedding_list import EmbeddingList
query = EmbeddingList()
query.add(query_clip_vec_1)
query.add(query_clip_vec_2)
client.search(
collection_name=“videos”,
data=[query],
anns_field="clips[clip_embedding_list]",
search_params={“metric_type”: “MAX_SIM_COSINE”},
limit=10,
)
Esta búsqueda responde: ¿Qué videos son la mejor coincidencia general para este conjunto de clips de consulta?
Se ajusta a la recuperación video-a-video, la búsqueda de productos con múltiples imágenes, la recuperación estilo ColBERT y ColPali, y otros casos donde tanto la consulta como la entidad almacenada están representadas por múltiples vectores.
Búsqueda a nivel de elemento: un vector de consulta encuentra un clip dentro de una entidad
La búsqueda a nivel de elemento utiliza un vector de consulta regular. Cada vector en clips[clip_embedding] participa en la búsqueda ANN como un candidato independiente. Cada coincidencia identifica la entidad principal y el desplazamiento del elemento coincidente.
client.search(
collection_name="videos",
data=[query_vec],
anns_field="clips[clip_embedding]",
search_params={"metric_type": "COSINE"},
limit=10,
output_fields=["id", "title", "clips"],
)
Para buscar solo clips seleccionados, adjunte un element_filter cuyas condiciones escalares se apliquen al mismo clip:
client.search(
collection_name="videos",
data=[query_vec],
anns_field="clips[clip_embedding]",
search_params={"metric_type": "COSINE"},
filter='element_filter(clips, $[scene_type] == "kitchen" && $[label_confidence] > 0.8)',
limit=10,
output_fields=["id", "title", "clips"],
)
El filtro no selecciona primero un clip de cocina y luego busca un clip de alta confianza diferente. Tanto los predicados como el candidato vectorial se refieren al mismo elemento Struct.
Una respuesta sin agrupar podría verse así:
Plaintext
id = 1, offset = 1, distance = 0.91
id = 8, offset = 4, distance = 0.88
id = 1, offset = 3, distance = 0.84
La misma entidad puede aparecer más de una vez porque varios clips pueden coincidir. Eso es útil cuando la aplicación necesita mostrar no solo qué video o documento es relevante, sino también qué clip o pasaje produjo la coincidencia.
| Aspecto | Búsqueda EmbeddingList | Búsqueda a nivel de elemento |
|---|---|---|
| Entrada de consulta | Uno o más vectores de consulta en un EmbeddingList | Un vector de consulta regular |
| Ejemplo de objetivo | clips[clip_embedding_list] | clips[clip_embedding] |
| Familia de métricas | MAX_SIM* | Métricas regulares como COSINE, IP o L2 |
| Unidad candidata ANN | La lista de incrustaciones de la entidad principal | Cada vector de elemento Struct |
| Identidad del resultado | Entidad principal | Entidad principal más desplazamiento de elemento |
| Caso de uso típico | Comparar una consulta multi-vector contra una entidad multi-vector | Encontrar el clip, imagen, pasaje, parche o hecho más relevante |
Para admitir ambos modos en una sola colección, defina e indexe subcampos vectoriales separados. La forma de consulta, la familia de métricas y el índice objetivo deben coincidir.
La indexación EmbeddingList es una decisión de calidad-costo
Con una incrustación por entidad, un índice ANN encuentra entidades cercanas a un vector de consulta. La búsqueda EmbeddingList es más costosa porque la relevancia depende de interacciones por pares entre dos listas de vectores.
Calcular MaxSim exacto contra cada vector en cada entidad produce la clasificación de referencia más limpia, pero un escaneo completo suele ser demasiado costoso para la recuperación en línea. Por lo tanto, Milvus utiliza un modelo de dos etapas:
- Una estrategia aproximada recupera entidades principales candidatas.
- Cuando
emb_list_rerankestá habilitado, Milvus recalcula MaxSim sobre esos candidatos para producir la clasificación final.
Recuperar más candidatos de primera etapa generalmente mejora la probabilidad de que los verdaderos mejores resultados lleguen al reclasificador, pero también aumenta la latencia y el cómputo. Las tres estrategias difieren principalmente en cómo producen ese conjunto de candidatos.
| Estrategia | Representación candidata de primera etapa | Buen punto de partida cuando | Compensación principal |
|---|---|---|---|
| TokenANN | Indexa cada vector en cada lista de incrustaciones. Los vectores de consulta ejecutan ANN de forma independiente; las coincidencias se agregan de vuelta a las entidades principales antes del reclasificación MaxSim. | La calidad es la prioridad, las listas son cortas o medianas, y los vectores individuales son discriminativos. | El tamaño del índice y el trabajo de búsqueda de primera etapa crecen con la longitud de la lista y el número de vectores de consulta. |
| MUVERA | Codifica cada lista de incrustaciones en un vector de dimensión fija mediante proyecciones aleatorias, luego ejecuta ANN ordinario. | TokenANN es demasiado pesado y se prefiere compresión sin un pipeline de entrenamiento. | La codificación pierde información; configuraciones de proyección más fuertes aumentan la dimensionalidad codificada y el costo ANN. |
| LEMUR | Entrena un modelo que mapea una lista de incrustaciones a un vector de entidad principal de dimensión fija. | Las incrustaciones son menos discriminativas, las listas son grandes, o la carga de trabajo es visual o multimodal. | Requiere entrenamiento y puede ser sensible a la distribución del corpus y al sesgo de longitud de documento. |
Ninguna estrategia es la mejor para cada carga de trabajo. Comience con los datos objetivo y la distribución de consultas:
- Use TokenANN como referencia de calidad primero cuando el tamaño del conjunto de datos lo permita.
- Pruebe MUVERA cuando el índice de TokenANN o la recuperación de candidatos se vuelva demasiado costosa a medida que crece la longitud de la lista, y quiera evitar un pipeline de entrenamiento.
- Evalúe LEMUR cuando el espacio de incrustaciones sea ruidoso o débilmente discriminativo, o cuando la carga de trabajo sea visual o multimodal.
- Mida recall o nDCG junto con latencia y tamaño de índice. Una estrategia que funciona para texto corto puede comportarse de manera diferente con longitudes de documento de cola larga o miles de parches visuales.
StructArray aborda un problema: cómo representar elementos alineados, filtrables y portadores de vectores dentro de una sola entidad. La estrategia EmbeddingList aborda otro: cómo aproximar MaxSim a un costo aceptable para un modelo y corpus particulares.
La búsqueda híbrida hace explícita la identidad del resultado
La recuperación en producción rara vez sigue una única ruta vectorial. Una solicitud de video puede combinar una incrustación de video de nivel superior, una o más incrustaciones a nivel de clip, una señal de subtítulo o transcripción, y un reclasificador.
Una vez que los candidatos a nivel de elemento ingresan a ese pipeline, el motor debe decidir qué identifica a un candidato final.
| Composición de solicitud híbrida | Alcance del candidato final | Identidad del resultado |
|---|---|---|
| Todas las sub-búsquedas son a nivel de elemento y apuntan a subcampos vectoriales bajo el mismo StructArray | Nivel de elemento | Clave primaria más campo StructArray más desplazamiento de elemento |
| Se incluye un campo vectorial de nivel superior | Nivel de entidad | Clave primaria |
| Se incluye una solicitud EmbeddingList | Nivel de entidad | Clave primaria |
| Las solicitudes a nivel de elemento apuntan a diferentes campos StructArray | Nivel de entidad | Clave primaria |
La primera configuración preserva la identidad del elemento porque el desplazamiento 3 se refiere al mismo elemento Struct para cada sub-búsqueda bajo un StructArray principal dado. Esto se ajusta a una aplicación que quiere devolver el clip o pasaje más relevante después de fusionar varias señales a nivel de elemento.
Las otras configuraciones mezclan granularidades de candidatos o espacios de nombres de elementos. Por lo tanto, una coincidencia de elemento debe consolidarse en una puntuación a nivel de entidad antes del reclasificación final. Milvus admite varias estrategias de consolidación:
| Estrategia de consolidación | Puntuación de entidad a partir de las coincidencias de elemento devueltas | Condición importante |
|---|---|---|
max | Mejor puntuación de elemento | Funciona con métricas vectoriales regulares compatibles |
sum | Suma de todas las puntuaciones de elemento devueltas | Use con métricas de correlación positiva como IP o COSINE |
avg | Promedio de las puntuaciones de elemento devueltas | Funciona con métricas vectoriales regulares compatibles |
topk_sum | Suma de las mejores K puntuaciones de elemento devueltas | Requiere un topk positivo; use con IP o COSINE |
topk_avg | Promedio de las mejores K puntuaciones de elemento devueltas | Requiere un topk positivo |
La consolidación opera solo sobre las coincidencias de elemento devueltas por esa sub-búsqueda ANN; no escanea cada elemento de la entidad después de la recuperación. Por lo tanto, el limit de la solicitud controla qué coincidencias de elemento están disponibles para la función de consolidación.
Esta elección da forma a la semántica de recuperación, no solo al formato de salida. Si la aplicación presenta un clip o pasaje, preservar el desplazamiento a través de la fusión es natural. Si presenta un video, producto o documento, la consolidación a nivel de entidad es natural. Cuando las señales operan a diferentes granularidades, el sistema necesita una regla explícita de puntuación de elemento a entidad.
StructArray mueve ese problema de identidad-y-consolidación del posprocesamiento ad hoc al modelo de ejecución de búsqueda.
Cómo ejecuta Milvus StructArray sin tratarlo como un blob
El modelo orientado al usuario es ARRAY<STRUCT>. Sin embargo, almacenar todo el valor como un solo blob opaco haría ineficientes los índices de subcampos, los filtros y la salida selectiva.
Milvus utiliza un diseño de padre lógico, columnas hijas físicas.
En la capa de esquema, clips es el campo padre lógico. Define propiedades como el esquema Struct, la capacidad máxima y la anulabilidad. Sus subcampos se normalizan en rutas como clips[clip_embedding_list], clips[clip_embedding], clips[scene_type] y clips[label_confidence].
Los subcampos escalares siguen rutas de almacenamiento de arreglos escalares por entidad, mientras que los subcampos vectoriales siguen rutas de arreglos vectoriales. Cada subcampo puede entonces usar la ruta de datos apropiada para su tipo: filtrado escalar e índices escalares para metadatos, e índices vectoriales y búsqueda ANN para incrustaciones.
En la ingesta, el Proxy expande la lista Struct anidada en columnas hijas tipadas. Durante la ejecución, Milvus mantiene la relación entre cada elemento físico y su entidad principal. Conceptualmente, esa relación se ve así:
Plaintext
entity 0 -> elements [0, 1, 2]
entity 1 -> elements [3]
entity 2 -> elements []
entity 3 -> elements [4, 5, 6, 7]
Cuando la búsqueda a nivel de elemento devuelve un ID de elemento físico, Milvus lo mapea de vuelta a la entidad principal y al desplazamiento del elemento. Cuando element_filter produce un mapa de bits a nivel de elemento, el motor lo alinea con la visibilidad de la entidad principal, las eliminaciones y otros filtros.
Al devolver resultados, Milvus utiliza el esquema lógico y los desplazamientos compartidos para reconstruir la forma StructArray que la aplicación insertó. El sistema puede ejecutar sobre columnas hijas tipadas mientras el usuario continúa leyendo y escribiendo objetos anidados naturales. Este diseño físico hace que StructArray sea más que JSON tipado: la relación anidada participa en el modelo de índice y ejecución.
Dónde encaja StructArray y dónde no
StructArray es un gran ajuste cuando todas las siguientes condiciones son verdaderas:
- La aplicación tiene una entidad principal significativa, como un video, producto, documento, página visual o registro de memoria.
- Cada entidad principal contiene un conjunto ordenado y de longitud variable de elementos locales.
- Esos elementos necesitan sus propios metadatos escalares, vectores, o ambos.
- La búsqueda o el filtrado deben preservar la relación entre subcampos en el mismo desplazamiento de elemento.
- La aplicación necesita recuperación multi-vector a nivel de entidad, coincidencias a nivel de elemento, o ambas.
StructArray no es automáticamente mejor para cada colección. Un documento corto o una consulta simple pueden ser bien atendidos por una única incrustación densa. La indexación multi-vector agrega costos de almacenamiento y búsqueda, por lo que la representación adicional debe ganarse su lugar mediante una mejor calidad de recuperación o una granularidad de resultados más útil.
Los límites actuales del esquema y la ejecución también importan:
Structse admite como tipo de elemento de unArray, no como campo de colección de nivel superior.- Todos los elementos en un StructArray comparten un esquema predefinido.
max_capacityes obligatorio y limita el número de elementos por entidad.- Los subcampos
Struct,Array,ArrayOfStructyJSONanidados no se admiten dentro de un StructArray. - Un subcampo vectorial acepta un índice. Use subcampos vectoriales separados para búsqueda EmbeddingList y a nivel de elemento cuando se requieran ambos.
- Los subcampos vectoriales deben indexarse antes de la búsqueda. Los subcampos escalares muy utilizados en filtros deben indexarse apropiadamente.
- El esquema de subcampos es fijo después de crear el campo StructArray, así que planifique los atributos de los elementos antes del lanzamiento de producción.
Estas restricciones hacen que el modelo sea más estrecho que el anidamiento arbitrario de una base de datos documental, pero también le dan a Milvus suficiente estructura para razonar sobre la identidad de los elementos, indexar cada subcampo y ejecutar en dos granularidades de búsqueda.
StructArray mantiene la evidencia local como ciudadano de primera clase sin perder la entidad
StructArray le da a Milvus un objeto de recuperación que los esquemas planos luchan por representar: una entidad principal con un conjunto ordenado de elementos estructurados. Las relaciones entre esos elementos participan en el filtrado, la indexación y la búsqueda, en lugar de existir solo en el almacenamiento.
Cada elemento conserva sus propios metadatos e incrustaciones. Los elementos pueden satisfacer predicados escalares de mismo elemento, participar juntos en la búsqueda EmbeddingList a nivel de entidad, o competir independientemente en la búsqueda a nivel de elemento. Al mismo tiempo, permanecen adjuntos a la entidad principal cuyos metadatos, permisos e identidad de aplicación les dan contexto.
Para clips de video, imágenes de producto, pasajes de documento, parches visuales y fragmentos de memoria, la evidencia local puede buscarse y filtrarse sin perder la entidad a la que pertenece. Las decisiones de diseño restantes son explícitas: seleccione la granularidad de búsqueda, asigne a cada subcampo vectorial la métrica e índice correspondientes, y decida si los resultados híbridos deben preservar los desplazamientos de elemento o consolidarse de vuelta a entidades.
Pruebe StructArray en Milvus 3.0
StructArray está disponible en Milvus 3.0. Comience con la descripción general de StructArray. Si está evaluando la recuperación multi-vector a nivel de entidad, lea la guía de estrategias EmbeddingList. Para conocer la granularidad de resultados y el comportamiento de consolidación, consulte Búsqueda híbrida con StructArray.
Para obtener un contexto más amplio del lanzamiento, consulte el blog de lanzamiento de Milvus 3.0, las notas de versión y el repositorio milvus-io/milvus.
Zilliz Cloud también admite StructArray y búsqueda EmbeddingList para implementaciones administradas. Revise la guía de StructArray de Zilliz Cloud para conocer los límites específicos del servicio. En Zilliz Cloud, los operadores escalares en StructArray están documentados actualmente para clústeres On-Demand.
Para discutir un diseño de esquema o recuperación con el equipo, únase a la comunidad de Discord de Milvus o reserve una sesión de Milvus Office Hours.
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



