Elasticsearch client for Rust: elasticsearch-rs
Elasticsearch is a powerful distributed search and analytics system built on Apache Lucene. To interact with it from Rust applications, there is an official client — elasticsearch-rs. This library provides a complete set of tools for working with the Elasticsearch REST API, including indexing, search, aggregations, and cluster management. In this article, we will thoroughly cover installation, configuration, and the main features of elasticsearch-rs with code examples.
What is elasticsearch-rs?
elasticsearch-rs is the official asynchronous Elasticsearch client for the Rust language, developed by Elastic. It is based on the popular asynchronous HTTP client library reqwest and provides a type-safe API for all Elasticsearch endpoints. Key advantages:
- Full support for Elasticsearch 7.x and 8.x — all core operations: CRUD, search, aggregations, index management.
- Asynchronous — uses async/await, allowing efficient handling of many requests.
- Type safety — request and response structures are strictly typed, reducing runtime errors.
- Automatic serialization/deserialization — via
serdeandserde_json. - Authentication support — Basic Auth, API keys, SSL/TLS.
Installation
Add the dependency to Cargo.toml:
[dependencies]elasticsearch = "8.14.0"serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"tokio = { version = "1", features = ["full"] }Basic connection
Let's create a client connecting to a local Elasticsearch instance:
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); // Check connection let response = client.ping().send().await?; println!("Elasticsearch is available: {}", response.status_code()); Ok(())}Basic operations: CRUD
1. Indexing a document
Add a document with book information to the books index:
#[derive(Serialize, Deserialize, Debug)]struct Book { title: String, author: String, year: u16, isbn: String,}
let book = Book { title: "Rust in Action".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!("Document indexed: {:?}", response.body());2. Getting a document
let response = client .get(GetParts::IndexId("books", "1")) .send() .await?;
if response.status_code().is_success() { let book: Book = response.json().await?; println!("Document found: {:?}", book);}3. Updating a document
let response = client .update(UpdateParts::IndexId("books", "1")) .body(json!({ "doc": { "year": 2024 } })) .send() .await?;
println!("Updated: {:?}", response.body());4. Deleting a document
let response = client .delete(DeleteParts::IndexId("books", "1")) .send() .await?;
println!("Deleted: {:?}", response.body());Search using Query DSL
Perform a full-text search on the title field:
use elasticsearch::SearchParts;
l