# Dec 18th, 2025: \[ES\] Búsqueda Vectorial con ES|QL

**URL:** <https://discuss.elastic.co/t/dec-18th-2025-es-busqueda-vectorial-con-es-ql/384026>\
**Category:** Advent Calendar\
**Tags:** esql\
**Created:** [December 18, 2025, 8:00am UTC](https://discuss.elastic.co/t/dec-18th-2025-es-busqueda-vectorial-con-es-ql/384026 "2025-12-18T08:00:18Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Carlos\_D](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/carlos_d/32/126245_2.png) [@Carlos\_D](https://discuss.elastic.co/u/Carlos_D)\
**Post date:** [December 18, 2025, 8:00am UTC](https://discuss.elastic.co/t/dec-18th-2025-es-busqueda-vectorial-con-es-ql/384026/1 "2025-12-18T08:00:18Z")

</div>

This post is also available [in English](https://discuss.elastic.co/t/384024).

 ![social-advent-2021-Day18](https://us1.discourse-cdn.com/elastic/original/3X/4/7/47f6f68530476f818ac9a9cc35fa2d39c2165750.png)

# Búsqueda Vectorial con ES|QL

Hoy descubrimos una de las incorporaciones más interesantes en ES|QL: Soporte nativo para campos dense\_vector, y las funciones para buscar en ellos: `KNN` y las funciones de similitud vectorial. Si tenías curiosidad por la búsqueda vectorial pero la sintaxis del Query DSL te parecía un poco intimidantes, ES|QL está a punto de convertirse en tu mejor aliado.

## ¿Por qué ES|QL para Búsqueda Vectorial?

ES|QL es el futuro de Elasticsearch - te permite realizar tus consultas como si fueran una serie de pasos en un proceso. Añadir búsqueda vectorial a ES|QL te proporciona un control experto sobre cómo realizas consultas semánticas usando vectores, ajustando el método de búsqueda (ya sea vecinos más cercanos aproximados mediante `KNN`, o búsqueda exacta mediante funciones de similitud vectorial).

## Preparando Nuestro Entorno de Pruebas

Vamos a crear un índice simple con un campo `dense_vector` para almacenar algunos vectores sobre productos. Lo mantendremos muy pequeño, sólo 3 dimensiones, para poder razonar sobre los vectores con más facilidad.

```auto
PUT products-vectors
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "category": {
        "type": "keyword"
      },
      "embedding": {
        "type": "dense_vector",
        "dims": 3,
        "similarity": "cosine"
      }
    }
  }
}

```

El parámetro clave es `similarity: cosine` (cómo medimos la cercanía de los vectores - otras opciones incluyen `l2_norm` y `dot_product`).

Ahora añadiremos algunos productos de ejemplo con sus correspondientes vectores (embeddings):

```auto
POST products-vectors/_bulk
{"index": {"_id": "1"}}
{"name": "Warm Winter Jacket", "category": "clothing", "embedding": [0.9, 0.1, 0.2]}
{"index": {"_id": "2"}}
{"name": "Summer Beach Shorts", "category": "clothing", "embedding": [0.1, 0.9, 0.3]}
{"index": {"_id": "3"}}
{"name": "Cozy Wool Sweater", "category": "clothing", "embedding": [0.85, 0.15, 0.25]}
{"index": {"_id": "4"}}
{"name": "Running Sneakers", "category": "footwear", "embedding": [0.4, 0.5, 0.8]}
{"index": {"_id": "5"}}
{"name": "Hiking Boots", "category": "footwear", "embedding": [0.6, 0.3, 0.7]}

```

Puedes usar ES|QL para recuperar tus datos, incluyendo los embeddings vectoriales:

```auto
FROM products-vectors

```

En este ejemplo sencillo, digamos que nuestra primera dimensión representa "abrigado", la segunda "veraniego", y la tercera "actividades al aire libre". Los embeddings reales de modelos como E5 u OpenAI tendrían cientos de dimensiones, pero el principio sigue siendo el mismo.

## Búsqueda usando la función KNN

La función `KNN` de ES|QL realiza búsqueda aproximada de los k vecinos más cercanos en tus vectores:

```auto
FROM products-vectors METADATA _score
| WHERE KNN(embedding, [0.88, 0.12, 0.22])
| KEEP name, category, _score
| SORT _score DESC
| LIMIT 3

```

Entendamos bien esta query:

- `METADATA _score`: Necesitamos este metadato para obtener la puntuación de la función KNN

- `KNN(embedding, [0.88, 0.12, 0.22])` : Encuentra los vecinos más cercanos a nuestro vector de consulta (query)

- El vector de consulta (query) `[0.88, 0.12, 0.22]` representa algo "abrigado" (primera dimensión alta)

¿El resultado? Nuestros artículos de ropa de abrigo aparecen en la parte superior:

| name | category | \_score |
| --- | --- | --- |
| Warm Winter Jacket | clothing | 0.9994338750839233 |
| Cozy Wool Sweater | clothing | 0.9992702007293701 |
| Hiking Boots | footwear | 0.9067620635032654 |

## Combinando KNN con Filtros

Uno de los superpoderes de ES|QL es que puedes combinar fácilmente búsqueda vectorial con filtros tradicionales:

```auto
FROM products-vectors 
METADATA _score
| WHERE category == "clothing" AND KNN(embedding, [0.88, 0.12, 0.22])
| KEEP name, _score
| SORT _score DESC
| LIMIT 3

```

Esto aplica el filtrado como un pre-filtro antes de ejecutar la búsqueda KNN. ¡Eficiente y legible!

| name | category | \_score |
| --- | --- | --- |
| Warm Winter Jacket | clothing | 0.9994338750839233 |
| Cozy Wool Sweater | clothing | 0.9992702007293701 |
| Summer Beach Shorts | clothing | 0.658316433429718 |

## Ajustando con Parámetros Opcionales

La función `KNN` acepta parámetros con nombre para tener un mayor control:

```auto
FROM products-vectors METADATA _score
| WHERE KNN(embedding, [0.1, 0.85, 0.3], {"k": 2, "boost": 1.5, "min_candidates": 50, "rescore_oversample": 3, "similarity": 0.0001})
| KEEP name, _score
| SORT _score DESC

```

Los parámetros permitidos son:

- **k** : Número de vecinos a devolver (implícitamente desde LIMIT)

- **boost** : Multiplicador de puntuación (por defecto: 1.0)

- **min\_candidates** : Mínimo de candidatos a considerar por shard (mayor = más preciso pero más lento)

- **similarity** : La similitud mínima para considerar un resultado

- **visit\_percentage** : El porcentaje de vectores a explorar por shard al hacer búsqueda knn con `bbq_disk`

- **rescore\_oversample** : Aplica el factor de sobremuestreo especificado a `k` en la búsqueda

## Búsqueda usando Funciones de Similitud Vectorial

`KNN` es genial para buscar vectores a gran escala porque es _aproximada_ - lo que significa que intentará encontrar resultados suficientemente buenos, pero sin considerar todos los posible resultados. Esto es lo que permite que `KNN` sea eficiente, ya que no tiene que considerar todos los documentos posibles y compararlos con la consulta uno a uno.

En caso de que realmente queramos examinar todos los resultados (porque ya hemos filtrado nuestros resultados, o porque no tenemos muchos documentos de partida), podemos usar funciones de similitud vectorial para calcular la similitud entre nuestra consulta y cada elemento:

```auto
FROM products-vectors
| EVAL my_score = V_COSINE(embedding, [0.1, 0.85, 0.3]) + 1.0
| KEEP name, my_score
| SORT my_score DESC

```

Las funciones de similitud vectorial te permiten realizar un _score_ personalizado para vectores, y tener un cálculo exacto de los vecinos más cercanos.

## Bonus: Función TEXT\_EMBEDDING

Si tienes un endpoint de inferencia configurado, puedes generar embeddings directamente utilizando:

```auto
FROM products-vectors 
METADATA _score
| WHERE KNN(embedding, TEXT_EMBEDDING("cozy winter wear", "my-embedding-model"))
| KEEP name, _score
| SORT _score DESC
| LIMIT 3

```

¡No necesitas precalcular los vectores de tu consulta—ES|QL lo hace por tí!

## Conclusión

Las capacidades de búsqueda vectorial de ES|QL proporcionan un control total para la búsqueda semántica. Ajustar cómo obtienes los vecinos más cercanos para una consulta, o calcular un _score_ personalizado, es posible gracias al soporte de ES|QL para el tipo de campo `dense_vector`, la función de búsqueda `KNN`, y las funciones de similitud vectorial.

Ya estés construyendo un sistema de recomendaciones, un motor de búsqueda semántica, o simplemente explorando tus datos vectoriales, la combinación de `KNN`, filtros y agregaciones convierte a ES|QL en un compañero ideal.
