Rust Elasticsearch Example: Connecting and Querying Elasticsearch with Rust
Elasticsearch is a powerful open-source search and analytics engine. Rust, with its performance and safety, is a great fit for building efficient and reliable applications that interact with Elasticsearch. In this guide, we’ll show you how to connect to Elasticsearch using Rust and perform basic operations like indexing, searching, and deleting documents.
Prerequisites
- Install Elasticsearch:
- Download and install Elasticsearch from the official website.
- Install Rust:
Install Rust using rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Start Elasticsearch:
./bin/elasticsearch
Setting Up the Rust Project
1. Create a New Rust Project
Create a new Rust project:
cargo new rust_elasticsearch_example
cd rust_elasticsearch_example
2. Add Dependencies
Update your Cargo.toml
file with the following dependencies:
[dependencies]
elasticsearch = "8.0"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
elasticsearch
: Official Elasticsearch client for Rust.serde
: For serializing and deserializing JSON data.tokio
: Asynchronous runtime required by the Elasticsearch client.
Run cargo build
to download and compile the dependencies.
Example: Basic Operations with Elasticsearch
Here’s how to connect to Elasticsearch and perform basic operations.
1. Connecting to Elasticsearch
Replace the content of src/main.rs
with:
use elasticsearch::{Elasticsearch, Error, SearchParts};
use serde_json::{json, Value};
use tokio;
#[tokio::main]
async fn main() -> Result<(), Error> {
// Create an Elasticsearch client
let client = Elasticsearch::default();
println!("Connected to Elasticsearch!");
Ok(())
}
Run the application:
cargo run
If everything is set up correctly, you should see:
Connected to Elasticsearch!
2. Indexing a Document
Add a function to index a document:
async fn index_document(client: &Elasticsearch) -> Result<(), Error> {
let doc = json!({
"title": "Rust Elasticsearch Example",
"content": "This is a document indexed in Elasticsearch using Rust.",
"tags": ["rust", "elasticsearch", "example"],
});
let response = client
.index(elasticsearch::IndexParts::IndexId("my_index", "1"))
.body(doc)
.send()
.await?;
println!("Document indexed: {:?}", response.status_code());
Ok(())
}
Call the function in main
:
index_document(&client).await?;
Run the program to index the document.
3. Searching for Documents
Add a function to search for documents:
async fn search_documents(client: &Elasticsearch) -> Result<(), Error> {
let response = client
.search(SearchParts::Index(&["my_index"]))
.body(json!({
"query": {
"match": {
"content": "Rust"
}
}
}))
.send()
.await?;
let response_body: Value = response.json().await?;
println!("Search results: {:#?}", response_body);
Ok(())
}
Call the function in main
:
search_documents(&client).await?;
Run the program to see search results.
4. Deleting a Document
Add a function to delete a document:
async fn delete_document(client: &Elasticsearch) -> Result<(), Error> {
let response = client
.delete(elasticsearch::DeleteParts::IndexId("my_index", "1"))
.send()
.await?;
println!("Document deleted: {:?}", response.status_code());
Ok(())
}
Call the function in main
:
delete_document(&client).await?;
Run the program to delete the document.
Full Example
Here’s the complete code for connecting to Elasticsearch, indexing, searching, and deleting documents:
use elasticsearch::{Elasticsearch, Error, SearchParts};
use serde_json::{json, Value};
use tokio;
#[tokio::main]
async fn main() -> Result<(), Error> {
let client = Elasticsearch::default();
println!("Connected to Elasticsearch!");
// Index a document
index_document(&client).await?;
// Search for documents
search_documents(&client).await?;
// Delete a document
delete_document(&client).await?;
Ok(())
}
async fn index_document(client: &Elasticsearch) -> Result<(), Error> {
let doc = json!({
"title": "Rust Elasticsearch Example",
"content": "This is a document indexed in Elasticsearch using Rust.",
"tags": ["rust", "elasticsearch", "example"],
});
let response = client
.index(elasticsearch::IndexParts::IndexId("my_index", "1"))
.body(doc)
.send()
.await?;
println!("Document indexed: {:?}", response.status_code());
Ok(())
}
async fn search_documents(client: &Elasticsearch) -> Result<(), Error> {
let response = client
.search(SearchParts::Index(&["my_index"]))
.body(json!({
"query": {
"match": {
"content": "Rust"
}
}
}))
.send()
.await?;
let response_body: Value = response.json().await?;
println!("Search results: {:#?}", response_body);
Ok(())
}
async fn delete_document(client: &Elasticsearch) -> Result<(), Error> {
let response = client
.delete(elasticsearch::DeleteParts::IndexId("my_index", "1"))
.send()
.await?;
println!("Document deleted: {:?}", response.status_code());
Ok(())
}
Best Practices
- Error Handling:
- Use proper error handling with
Result
to manage failures gracefully.
- Use proper error handling with
- Batch Operations:
- Use the
_bulk
API for indexing or deleting multiple documents efficiently.
- Use the
- Environment Variables:
- Store sensitive configurations like Elasticsearch URLs and credentials in environment variables.
- Testing:
- Test your application against a local or staging Elasticsearch instance before deploying to production.
Conclusion
Rust's official Elasticsearch client provides an efficient and type-safe way to interact with Elasticsearch. By following this guide, you can perform essential operations like indexing, searching, and deleting documents. This example serves as a foundation for building robust search applications with Rust and Elasticsearch. Start integrating Elasticsearch into your Rust projects today!