Cliente Elasticsearch para Rust: guía de elasticsearch-rs

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Cliente Elasticsearch para Rust: elasticsearch-rs

Elasticsearch es un potente sistema distribuido de búsqueda y análisis basado en Apache Lucene. Para interactuar con él desde aplicaciones en Rust, existe el cliente oficial: elasticsearch-rs. Esta biblioteca ofrece un conjunto completo de herramientas para trabajar con la API REST de Elasticsearch, incluyendo indexación, búsqueda, agregaciones y administración del clúster. En este artículo, analizaremos en detalle la instalación, configuración y las principales funcionalidades de elasticsearch-rs con ejemplos de código.

¿Qué es elasticsearch-rs?

elasticsearch-rs es el cliente asíncrono oficial de Elasticsearch para el lenguaje Rust, desarrollado por la empresa Elastic. Está basado en la popular biblioteca de cliente HTTP asíncrono reqwest y proporciona una API con tipos seguros para todos los endpoints de Elasticsearch. Sus principales ventajas son:

  • Soporte completo para Elasticsearch 7.x y 8.x — todas las operaciones principales: CRUD, búsqueda, agregaciones, administración de índices.
  • Asincronía — utiliza async/await, lo que permite procesar múltiples solicitudes de manera eficiente.
  • Seguridad de tipos — las estructuras de solicitudes y respuestas están fuertemente tipadas, lo que reduce errores en tiempo de ejecución.
  • Serialización/deserialización automática — a través de serde y serde_json.
  • Soporte de autenticación — Basic Auth, claves API, SSL/TLS.

Instalación

Agrega la dependencia en tu Cargo.toml:

[dependencies]
elasticsearch = "8.14.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1", features = ["full"] }

Conexión básica

Creemos un cliente que se conecte a una instancia local de Elasticsearch:

use elasticsearch::Elasticsearch;
use elasticsearch::http::transport::Transport;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let transport = Transport::single_node("http://localhost:9200")?;
    let client = Elasticsearch::new(transport);
    // Verificar conexión
    let response = client.ping().send().await?;
    println!("Elasticsearch disponible: {}", response.status_code());
    Ok(())
}

Operaciones principales: CRUD

1. Indexar un documento

Agreguemos un documento con información de un libro en el índice books:

#[derive(Serialize, Deserialize, Debug)]
struct Book {
    title: String,
    author: String,
    year: u16,
    isbn: String,
}

let book = Book {
    title: "Rust en acción".into(),
    author: "Tim McNamara".into(),
    year: 2023,
    isbn: "978-5-4461-2345-6".into(),
};

let response = client
    .index(IndexParts::IndexId("books", "1"))
    .body(json!(book))
    .send()
    .await?;

println!("Documento indexado: {:?}", response.body());

2. Obtener un documento

let response = client
    .get(GetParts::IndexId("books", "1"))
    .send()
    .await?;

if response.status_code().is_success() {
    let book: Book = response.json().await?;
    println!("Documento encontrado: {:?}", book);
}

3. Actualizar un documento

let response = client
    .update(UpdateParts::IndexId("books", "1"))
    .body(json!({
        "doc": { "year": 2024 }
    }))
    .send()
    .await?;

println!("Actualizado: {:?}", response.body());

4. Eliminar un documento

let response = client
    .delete(DeleteParts::IndexId("books", "1"))
    .send()
    .await?;

println!("Eliminado: {:?}", response.body());

Búsqueda con Query DSL

Realicemos una búsqueda de texto completo en el campo title:

use elasticsearch::SearchParts;

let response = client
    .search(SearchParts::Index(&["books"]))
    .body(json!({
        "query": {
            "match": {
                "title": "Rust"
            }
        }
    }))
    .send()
    .await?;

let search_result = response.json::<serde_json::Value>().await?;
println!("Resultados de búsqueda: {:?}", search_result);

Agregaciones

Ejemplo de una agregación para contar libros por año:

let response = client
    .search(SearchParts::Index(&["books"]))
    .body(json!({
        "aggs": {
            "por_año": {
                "terms": { "field": "year" }
            }
        }
    }))
    .send()
    .await?;

let aggs_result = response.json::<serde_json::Value>().await?;
println!("Agregaciones: {:?}", aggs_result);

Conclusión

elasticsearch-rs es una biblioteca robusta y completa para integrar Elasticsearch en aplicaciones Rust. Su diseño asíncrono, seguridad de tipos y soporte para todas las funcionalidades de Elasticsearch la convierten en la opción ideal para proyectos que requieren búsqueda y análisis de datos a gran escala. Con los ejemplos mostrados, ya puedes empezar a construir tus propias soluciones de búsqueda en Rust.

Recommendations