Búsqueda por rango con StructArray

Utiliza esta página para realizar una búsqueda por rango en los subcampos vectoriales de StructArray. La búsqueda por rango devuelve resultados vectoriales cuya puntuación o distancia se encuentra dentro de un límite especificado. Para los campos StructArray, utiliza la búsqueda por rango junto con la búsqueda vectorial a nivel de elemento, en la que cada elemento de Struct se busca de forma independiente.

Esta página utiliza la colección « tech_articles » de «Crear un campo StructArray». La colección cuenta con un campo StructArray denominado « chunks ». El subcampo vectorial « chunks[emb] » está indexado para la búsqueda a nivel de elemento con una métrica vectorial habitual, como « COSINE », « IP » o « L2 ».

Cómo se aplica la búsqueda por rango a StructArray

Modo de búsquedaComportamiento de la búsqueda por rangoGranularidad de los resultados
Búsqueda en EmbeddingListNo compatible.No aplicable.
Búsqueda a nivel de elementoUtiliza una consulta vectorial normal con ` radius ` y, opcionalmente, ` range_filter`.Nivel de elemento de estructura.
Búsqueda híbridaCompatible cuando la solicitud de StructArray se dirige a un campo vectorial a nivel de elemento. Las solicitudes a nivel de EmbeddingList no admiten la búsqueda por rango.Subbúsqueda a nivel de elemento, seguida de una reclasificación híbrida.

Si solo necesitas los elementos Struct más cercanos, empieza con la búsqueda vectorial básica con StructArray. Utiliza la búsqueda por rango cuando el resultado deba cumplir un límite de puntuación o distancia, en lugar de limitarse a una clasificación de los K primeros.

Antes de empezar

Prepara la colección, los datos y los índices antes de ejecutar la búsqueda por rango.

RequisitosDetalles
Campo StructArrayLa colección contiene un campo StructArray, como por ejemplo chunks.
Subcampo vectorial a nivel de elementoEl subcampo vectorial de destino es chunks[emb], no chunks[emb_list_vector].
Métrica de índiceEl subcampo vectorial se indexa con una métrica vectorial regular, como COSINE, IP o L2.
Datos de la consultaLa consulta es un vector normal, no un EmbeddingList.

Para la configuración del índice, consulta «Campos StructArray del índice».

Utilice «radius» y «range_filter»

Establezca ` radius ` para definir el límite de búsqueda. Establezca ` range_filter ` cuando también necesite un límite interior. La dirección depende de si es mejor una distancia menor o una puntuación de similitud mayor.

Tipo de métrica¿Es mejor una puntuación más alta?Condición de rango cuando se utiliza « range_filter »
L2No. Es mejor una distancia menor.range_filter <= distance < radius
IP, COSINESí. Cuanto mayor sea la puntuación, mejor.radius < distance <= range_filter

Cuando solo se establece « radius », la búsqueda por rango devuelve resultados que cumplen el límite exterior de la métrica. Elige los valores según la escala de puntuación o distancia de tus incrustaciones.

El siguiente ejemplo busca fragmentos individuales cuyos vectores « chunks[emb] » sean lo suficientemente similares al vector de consulta. Cada resultado encontrado representa un elemento Struct coincidente.

from pymilvus import MilvusClient

client = MilvusClient(
    uri="http://localhost:19530",
    token="root:Milvus",
)

query_vector = [0.19, 0.24, 0.30, 0.37]

results = client.search(
    collection_name="tech_articles",
    data=[query_vector],
    anns_field="chunks[emb]",
    search_params={
        "params": {
            "radius": 0.80,
            "range_filter": 0.95,
        },
    },
    limit=10,
    output_fields=[
        "doc_id",
        "title",
        "chunks[text]",
        "chunks[section]",
        "chunks[page]",
        "chunks[quality_score]",
    ],
)

for hits in results:
    for hit in hits:
        print(
            "doc_id:", hit["id"],
            "distance:", hit["distance"],
            "offset:", hit.get("offset"),
            "entity:", hit["entity"],
        )

En este ejemplo, « COSINE » es una métrica de tipo similitud, por lo que el rango de resultados es mayor que radius y menor o igual que range_filter. El valor « offset » identifica el elemento Struct coincidente en la matriz « chunks » cuando se devuelve.

Añadir filtros escalares

Se puede combinar la búsqueda de rango a nivel de elemento con el filtrado escalar de StructArray. Utilice un predicado de nivel superior para los campos de la entidad principal y utilice element_filter para restringir qué elementos Struct participan en la búsqueda de rango vectorial.

filter_expr = (
    'category == "search" && '
    'element_filter(chunks, '
    '$[section] == "index" && '
    '$[quality_score] > 0.9)'
)

results = client.search(
    collection_name="tech_articles",
    data=[query_vector],
    anns_field="chunks[emb]",
    search_params={
        "params": {
            "radius": 0.80,
            "range_filter": 0.95,
        },
    },
    filter=filter_expr,
    limit=10,
    output_fields=[
        "doc_id",
        "title",
        "category",
        "chunks[text]",
        "chunks[section]",
        "chunks[quality_score]",
    ],
)

El predicado de nivel superior selecciona las entidades candidatas. El predicado « element_filter » restringe la búsqueda de rango vectorial a los elementos Struct coincidentes. Para ver más ejemplos de filtrado, consulta «Búsqueda filtrada con StructArray».

Los campos vectoriales a nivel de elemento de StructArray admiten la búsqueda por rango en la búsqueda híbrida. Añade « radius » y, opcionalmente, « range_filter » a la solicitud « AnnSearchRequest » dirigida al campo vectorial a nivel de elemento de StructArray.

from pymilvus import AnnSearchRequest, RRFRanker

title_req = AnnSearchRequest(
    data=[query_vector],
    anns_field="title_vector",
    limit=10,
)

chunk_req = AnnSearchRequest(
    data=[query_vector],
    anns_field="chunks[emb]",
    param={
        "params": {
            "radius": 0.80,
            "range_filter": 0.95,
        },
    },
    limit=10,
    expr='element_filter(chunks, $[section] == "index")',
)

results = client.hybrid_search(
    collection_name="tech_articles",
    reqs=[title_req, chunk_req],
    ranker=RRFRanker(),
    limit=5,
    output_fields=[
        "doc_id",
        "title",
        "chunks[text]",
        "chunks[section]",
        "chunks[quality_score]",
    ],
)

En este ejemplo, solo la subpetición « chunks[emb] » utiliza parámetros de búsqueda por rango. La petición de StructArray sigue respetando la semántica a nivel de elemento: el límite del rango se aplica a los resultados del elemento Struct antes de que la búsqueda híbrida combine y vuelva a clasificar los resultados.

Interpretar los resultados del rango

Elemento de resultadoSignificado
idClave primaria de la entidad que contiene el elemento Struct coincidente.
distance o puntuaciónLa puntuación o distancia entre el vector de consulta y el vector del elemento Struct coincidente.
offsetPosición, contada a partir de cero, del elemento Struct coincidente en el campo StructArray al devolverse.
Claves primarias repetidasPosible. Más de un elemento Struct de la misma entidad puede estar dentro del rango especificado.
limitSe aplica a las coincidencias de elementos, no a entidades padre únicas.

Limitaciones

  • No utilices una consulta « EmbeddingList » ni una métrica « MAX_SIM* » para la búsqueda por rango en los subcampos vectoriales de StructArray. La búsqueda a nivel de EmbeddingList no admite la búsqueda por rango.

  • No combines la búsqueda por rango con la búsqueda por agrupación. Si necesitas un resultado por cada entidad principal, ejecuta una búsqueda a nivel de elemento sin parámetros de rango y utiliza la agrupación cuando sea compatible.

  • La búsqueda por rango híbrida es compatible con los campos vectoriales a nivel de elemento de StructArray. No es compatible con las solicitudes de StructArray a nivel de EmbeddingList.

Errores comunes

  • Realizar una búsqueda por rango en ` chunks[emb_list_vector]`, que está pensada para la búsqueda en `EmbeddingList`.

  • Utilizar ` MAX_SIM_COSINE ` en lugar de una métrica habitual, como ` COSINE `, para la búsqueda por rango a nivel de elemento.

  • Utilizar una consulta de « EmbeddingList » en lugar de una consulta vectorial normal.

  • Esperar que los resultados de la búsqueda por rango sean únicos por entidad principal. La búsqueda por rango devuelve resultados que coinciden con elementos de Struct.

  • Utilizar chunks.emb en lugar de la sintaxis de ruta de subcampo requerida chunks[emb].

Próximos pasos

  1. Para conocer los dos modos básicos de búsqueda vectorial con StructArray, consulta «Búsqueda vectorial básica con StructArray».

  2. Para añadir filtros escalares a la búsqueda por rango, consulta «Búsqueda filtrada con StructArray».

  3. Para obtener como máximo un resultado por entidad principal cuando sea posible, consulta «Búsqueda agrupada con StructArray».

  4. Para consultar los límites de búsqueda específicos de cada versión, lee «Límites de StructArray».