Cómo utilizar la búsqueda espacial y vectorial híbrida con Milvus

  • Engineering
March 18, 2026
Alden

Una consulta como "encontrar restaurantes románticos en un radio de 3 km" parece sencilla. No lo es, porque combina el filtrado por ubicación y la búsqueda semántica. La mayoría de los sistemas tienen que dividir esta consulta en dos bases de datos, lo que implica sincronizar los datos, fusionar los resultados en el código y una latencia adicional.

Milvus 2.6.4 elimina esta división. Con un tipo de datos nativo GEOMETRY y un índice R-Tree, Milvus puede aplicar restricciones de ubicación y semánticas juntas en una sola consulta. Esto hace que la búsqueda híbrida espacial y semántica sea mucho más fácil y eficiente.

Este artículo explica por qué era necesario este cambio, cómo funcionan GEOMETRY y R-Tree dentro de Milvus, qué mejoras de rendimiento cabe esperar y cómo configurarlo con el SDK de Python.

Consultas como "restaurantes románticos a menos de 3 km" son difíciles de manejar por dos razones:

  • "Romántico" requiere una búsqueda semántica. El sistema tiene que vectorizar las reseñas y etiquetas de los restaurantes y, a continuación, buscar coincidencias por similitud en el espacio de incrustación. Esto sólo funciona en una base de datos vectorial.
  • "En un radio de 3 km" requiere un filtrado espacial. Los resultados deben restringirse a "en un radio de 3 km del usuario" o, a veces, "dentro de un polígono de entrega o límite administrativo específico".

En una arquitectura tradicional, satisfacer ambas necesidades generalmente significaba ejecutar dos sistemas uno al lado del otro:

  • PostGIS / Elasticsearch para geofencing, cálculos de distancia y filtrado espacial.
  • Una base de datos vectorial para la búsqueda aproximada del vecino más cercano (RNA) sobre incrustaciones.

Este diseño de "dos bases de datos" crea tres problemas prácticos:

  • La penosa sincronización de datos. Si un restaurante cambia de dirección, hay que actualizar tanto el sistema geográfico como la base de datos vectorial. Si se omite una actualización, los resultados son incoherentes.
  • Mayor latencia. La aplicación tiene que llamar a dos sistemas y combinar sus resultados, lo que añade viajes de ida y vuelta por la red y tiempo de procesamiento.
  • Filtrado ineficaz. Si el sistema ejecutaba primero la búsqueda vectorial, a menudo devolvía muchos resultados que estaban lejos del usuario y había que descartar después. Si se aplicaba primero el filtrado por localización, el conjunto restante seguía siendo grande, por lo que el paso de búsqueda vectorial seguía siendo costoso.

Milvus 2.6.4 resuelve esto añadiendo soporte de geometría espacial directamente a la base de datos vectorial. La búsqueda semántica y el filtrado por localización se ejecutan ahora en la misma consulta. Con todo en un mismo sistema, la búsqueda híbrida es más rápida y fácil de gestionar.

Qué añade GEOMETRY a Milvus

Milvus 2.6 introduce un tipo de campo escalar llamado DataType.GEOMETRY. En lugar de almacenar ubicaciones como números separados de longitud y latitud, Milvus almacena ahora objetos geométricos: puntos, líneas y polígonos. Consultas como "¿está este punto dentro de una región?" o "¿está dentro de X metros?" se convierten en operaciones nativas. No hay necesidad de construir soluciones sobre coordenadas en bruto.

La implementación sigue elestándar OpenGIS Simple Features Access, por lo que funciona con la mayoría de las herramientas geoespaciales existentes. Los datos geométricos se almacenan y consultan utilizando WKT (Well-Known Text), un formato de texto estándar legible por humanos y analizable por programas.

Tipos de geometría admitidos

  • PUNTO: una única ubicación, como la dirección de una tienda o la posición en tiempo real de un vehículo.
  • LÍNEA: una línea, como la línea central de una carretera o una trayectoria de movimiento.
  • POLÍGONO: un área, como un límite administrativo o una geovalla
  • Tipos de recogida: MULTIPOINT, MULTILINESTRING, MULTIPOLYGON y GEOMETRYCOLLECTION

También admite operadores espaciales estándar, entre los que se incluyen:

  • Relaciones espaciales: contención (ST_CONTAINS, ST_WITHIN), intersección (ST_INTERSECTS, ST_CROSSES) y contacto (ST_TOUCHES).
  • Operaciones de distancia: cálculo de distancias entre geometrías (ST_DISTANCE) y filtrado de objetos dentro de una distancia determinada (ST_DWITHIN)

Cómo funciona la indexación R-Tree en Milvus

El soporte de GEOMETRÍA está integrado en el motor de consulta de Milvus, no sólo expuesto como una función de la API. Los datos ISpatial se indexan y procesan directamente dentro del motor utilizando el índice R-Tree (Rectangle Tree).

Un R-Tree agrupa los objetos cercanos mediante rectángulos de delimitación mínima (MBR). Durante una consulta, el motor omite las grandes regiones que no se solapan con la geometría de la consulta y sólo ejecuta comprobaciones detalladas en un pequeño conjunto de candidatos. Esto es mucho más rápido que escanear cada objeto.

Cómo construye Milvus el árbol R

El R-Tree se construye por capas:

NivelQué hace MilvusAnalogía intuitiva
Nivel de hojaPara cada objeto geométrico (punto, línea o polígono), Milvus calcula su rectángulo mínimo delimitador (RMB) y lo almacena como nodo hoja.Envuelve cada objeto en una caja transparente que se ajusta exactamente a él.
Niveles intermediosLos nodos hoja cercanos se agrupan (normalmente 50-100 a la vez), y se crea un MBR padre más grande para cubrirlos a todos.Colocación de paquetes del mismo vecindario en una única caja de entrega.
Nivel raízEsta agrupación continúa hacia arriba hasta que todos los datos están cubiertos por un único MBR raíz.Carga de todas las cajas en un camión de larga distancia.

Con esta estructura, la complejidad de las consultas espaciales se reduce de O(n) a O(log n). En la práctica, las consultas sobre millones de registros pueden pasar de cientos de milisegundos a unos pocos milisegundos, sin perder precisión.

Cómo se ejecutan las consultas: Filtrado en dos fases

Para equilibrar velocidad y corrección, Milvus utiliza una estrategia de filtrado en dos fases:

  • Filtro aproximado: el índice R-Tree comprueba primero si el rectángulo delimitador de la consulta se solapa con otros rectángulos delimitadores del índice. Esto elimina rápidamente la mayoría de los datos no relacionados y mantiene sólo un pequeño conjunto de candidatos. Como estos rectángulos tienen formas simples, la comprobación es muy rápida, pero puede incluir algunos resultados que en realidad no coinciden.
  • Filtro fino: los candidatos restantes se comprueban con GEOS, la misma biblioteca de geometría que utilizan sistemas como PostGIS. GEOS ejecuta cálculos geométricos exactos, como si las formas se cruzan o si una contiene a otra, para producir resultados finales correctos.

Milvus acepta datos geométricos en formato WKT ( Well-Known Text) pero los almacena internamente como WKB (Well-Known Binary). WKB es más compacto, lo que reduce el almacenamiento y mejora la E/S. Los campos GEOMETRY también admiten almacenamiento en mapa de memoria (mmap), por lo que los grandes conjuntos de datos espaciales no necesitan caber por completo en la RAM.

Mejoras de rendimiento con R-Tree

La latencia de las consultas se mantiene estable a medida que crecen los datos.

Sin un índice R-Tree, el tiempo de consulta aumenta linealmente con el tamaño de los datos: 10 veces más datos significa aproximadamente 10 veces más lentitud en las consultas.

Con R-Tree, el tiempo de consulta crece logarítmicamente. En conjuntos de datos con millones de registros, el filtrado espacial puede ser de decenas a cientos de veces más rápido que una exploración completa.

La velocidad no sacrifica la precisión

El R-Tree reduce los candidatos por cuadro delimitador y, a continuación, GEOS comprueba cada uno de ellos con matemáticas de geometría exacta. Todo lo que parece coincidir pero queda fuera del área de búsqueda se elimina en la segunda pasada.

El rendimiento de la búsqueda híbrida mejora

El árbol R elimina primero los registros que quedan fuera de la zona objetivo. A continuación, Milvus ejecuta la similitud vectorial (L2, IP o coseno) sólo en los candidatos restantes. Menos candidatos significa menor coste de búsqueda y mayor número de consultas por segundo (QPS).

Primeros pasos: GEOMETRÍA con el SDK de Python

Definir la colección y crear índices

Primero, defina un campo DataType.GEOMETRY en el esquema de la colección. Esto permite a Milvus almacenar y consultar datos geométricos.

from pymilvus import MilvusClient, DataType  
import numpy as np  
# Connect to Milvus  
milvus_client = MilvusClient("[http://localhost:19530](http://localhost:19530)")  
collection_name = "lb_service_demo"  
dim = 128  
# 1. Define schema  
schema = milvus_client.create_schema(enable_dynamic_field=True)  
schema.add_field("id", DataType.INT64, is_primary=True)  
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=dim)  
schema.add_field("location", DataType.GEOMETRY)  # Define geometry field  
schema.add_field("poi_name", DataType.VARCHAR, max_length=128)  
# 2. Create index parameters  
index_params = milvus_client.prepare_index_params()  
# Create an index for the vector field (e.g., IVF_FLAT)  
index_params.add_index(  
   field_name="vector",  
   index_type="IVF_FLAT",  
   metric_type="L2",  
   params={"nlist": 128}  
)  
# Create an R-Tree index for the geometry field (key step)  
index_params.add_index(  
   field_name="location",  
   index_type="RTREE"  # Specify the index type as RTREE  
)  
# 3. Create collection  
if milvus_client.has_collection(collection_name):  
   milvus_client.drop_collection(collection_name)  
milvus_client.create_collection(  
   collection_name=collection_name,  
   schema=schema,  
   index_params=index_params,  # Create the collection with indexes attached  
   consistency_level="Strong"  
)  
print(f"Collection {collection_name} created with R-Tree index.")  

Insertar datos

Al insertar datos, los valores geométricos deben estar en formato WKT (Well-Known Text). Cada registro incluye la geometría, el vector y otros campos.

# Mock data: random POIs in a region of Beijing  
data = []  
# Example WKT: POINT(longitude latitude)  
geo_points = [  
   "POINT(116.4074 39.9042)",  # Near the Forbidden City  
   "POINT(116.4600 39.9140)",  # Near Guomao  
   "POINT(116.3200 39.9900)",  # Near Tsinghua University  
]  
for i, wkt in enumerate(geo_points):  
   vec = np.random.random(dim).tolist()  
   data.append({  
       "id": i,  
       "vector": vec,  
       "location": wkt,  
       "poi_name": f"POI_{i}"  
   })  
res = milvus_client.insert(collection_name=collection_name, data=data)  
print(f"Inserted {res['insert_count']} entities.")  

Ejecutar una consulta híbrida espacial-vectorial (ejemplo)

Escenario: encontrar los 3 PDI más similares en el espacio vectorial y situados a menos de 2 kilómetros de un punto dado, como la ubicación del usuario.

Utilice el operador ST_DWITHIN para aplicar el filtro de distancia. El valor de la distancia se especifica en metros.

# Load the collection into memory  
milvus_client.load_collection(collection_name)  
# User location (WKT)  
user_loc_wkt = "POINT(116.4070 39.9040)"  
search_vec = np.random.random(dim).tolist()  
# Build the filter expression: use ST_DWITHIN for a 2000-meter radius filter  
filter_expr = f"ST_DWITHIN(location, '{user_loc_wkt}', 2000)"  
# Execute the search  
search_res = milvus_client.search(  
   collection_name=collection_name,  
   data=[search_vec],  
   filter=filter_expr,  # Inject geometry filter  
   limit=3,  
   output_fields=["poi_name", "location"]  
)  
print("Search Results:")  
for hits in search_res:  
   for hit in hits:  
       print(f"ID: {hit['id']}, Score: {hit['distance']:.4f}, Name: {hit['entity']['poi_name']}")  

Consejos para el uso en producción

  • Cree siempre un índice R-Tree en los campos GEOMETRÍA. Para conjuntos de datos superiores a 10.000 entidades, los filtros espaciales sin un índice RTREE retroceden a un escaneo completo, y el rendimiento cae bruscamente.
  • Utilice un sistema de coordenadas coherente. Todos los datos de localización deben utilizar el mismo sistema (por ejemplo, WGS84). Mezclar sistemas de coordenadas rompe los cálculos de distancia y contención.
  • Elija el operador espacial adecuado para la consulta. ST_DWITHIN para búsquedas "dentro de X metros". ST_CONTAINS o ST_WITHIN para geofencing y comprobaciones de contención.
  • Los valores de geometría nulos se gestionan automáticamente. Si el campo GEOMETRY es anulable (nullable=True), Milvus omite los valores NULL durante las consultas espaciales. No se necesita lógica de filtrado adicional.

Requisitos de despliegue

Para utilizar estas características en producción, asegúrese de que su entorno cumple los siguientes requisitos.

1. Versión de Milvus

Debe ejecutar Milvus 2.6.4 o posterior. Las versiones anteriores no admiten DataType.GEOMETRY ni el tipo de índice RTREE.

2. Versiones SDK

  • PyMilvus: actualice a la última versión (se recomienda la serie 2.6.x ). Esto es necesario para la correcta serialización WKT y para pasar parámetros de índice RTREE.
  • Java / Go / Node SDKs: compruebe las notas de la versión para cada SDK y confirme que están alineados con las definiciones de proto 2.6.4.

3. Bibliotecas de geometría incorporadas

El servidor Milvus ya incluye Boost.Geometry y GEOS, por lo que no necesita instalar estas bibliotecas usted mismo.

4. Uso de memoria y planificación de capacidad

Los índices R-Tree utilizan memoria extra. Cuando planifique la capacidad, recuerde presupuestar los índices geométricos así como los índices vectoriales como HNSW o IVF. El campo GEOMETRY admite el almacenamiento en mapa de memoria (mmap), que puede reducir el uso de memoria manteniendo parte de los datos en disco.

Conclusión

La búsqueda semántica basada en la localización requiere algo más que añadir un filtro geográfico a una consulta vectorial. Requiere tipos de datos espaciales incorporados, índices adecuados y un motor de consulta que pueda manejar la ubicación y los vectores conjuntamente.

Milvus 2.6.4 resuelve esto con campos GEOMETRY nativos e índices R-Tree. El filtrado espacial y la búsqueda vectorial se ejecutan en una única consulta, contra un único almacén de datos. El R-Tree se encarga de la poda espacial rápida, mientras que GEOS garantiza resultados exactos.

Para las aplicaciones que necesitan una recuperación que tenga en cuenta la ubicación, esto elimina la complejidad de ejecutar y sincronizar dos sistemas distintos.

Si está trabajando en una búsqueda espacial y vectorial consciente de la ubicación o híbrida, nos encantaría conocer su experiencia.

¿Tiene preguntas sobre Milvus? Únase a nuestro canal de Slack o reserve una sesión de 20 minutos de Milvus Office Hours.

    Try Managed Milvus for Free

    Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

    Get Started

    Like the article? Spread the word

    Sigue Leyendo