Elasticsearch client for Rust: official elasticsearch-rs library

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Elasticsearch client for Rust: elasticsearch-rs



elasticsearch-rs is the official asynchronous client for interacting with Elasticsearch from the Rust ecosystem. The library provides a complete set of tools for working with the search engine: from simple CRUD operations to complex aggregations and bulk requests. It is developed and maintained by the Elastic team, guaranteeing API relevance and compatibility with the latest versions of Elasticsearch.



Key Features



  • Full Elasticsearch API support — indexing, search, aggregations, index management, mapping, and cluster settings.
  • Asynchronous — built on top of tokio and reqwest, allowing thousands of requests to be processed without blocking threads.
  • Type safety — all requests and responses are strictly typed, validation errors are caught at compile time.
  • Bulk operations support — mass document loading and updating with automatic error handling.
  • SSL/TLS and authentication — built-in support for HTTPS, Basic Auth, API keys, and tokens.
  • Serialization via serde — documents are automatically converted to/from JSON using the serde crate.


Installation and Setup



Add the dependency to Cargo.toml:



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


Basic connection to a local Elasticsearch instance:



use elasticsearch::{Elasticsearch, Error};use url::Url;

#[tokio::main]async fn main() -> Result<(), Error> { let client = Elasticsearch::new( elasticsearch::http::transport::Transport::single_node( Url::parse("http://localhost:9200")? )? ); // Connection check let response = client.ping().send().await?; println!("Elasticsearch available: {}", response.status_code()); Ok(())}


Working with Documents



Indexing a Document



Define a structure for serialization:



use serde::{Serialize, Deserialize};

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


Indexing a new document:



use elasticsearch::{IndexParts, SearchParts};use serde_json::json;

async fn index_book(client: &Elasticsearch, book: &Book) -> Result<(), Error> { let response = client .index(IndexParts::IndexId("books", &book.isbn)) .body(book) .send() .await?; println!("Document indexed: {:?}", response); Ok(())}


Searching an Index



Full-text search example:



async fn search_books(client: &Elasticsearch, query: &str) -> Result, Error> {    let response = client        .search(SearchParts::Index(&["books"]))        .body(json!({            "query": {                "multi_match": {                    "query": query,                    "fields": ["title^2", "author"]                }            }        }))        .send()        .await?;        let response_body = response.json::().await?;    let hits = response_body["hits"]["hits"]        .as_array()        .unwrap_or(&vec![]);        let books: Vec = hits        .iter()        .filter_map(|hit| {            let source = hit["_source"].clone();            serde_json::from_value(source).ok()        })        .collect();        Ok(books)}


Bulk Operations for Mass Loading



Efficient loading of thousands of documents:



use elasticsear                    

Recommendations