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

  1. Install Elasticsearch:
  2. 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

  1. Error Handling:
    • Use proper error handling with Result to manage failures gracefully.
  2. Batch Operations:
    • Use the _bulk API for indexing or deleting multiple documents efficiently.
  3. Environment Variables:
    • Store sensitive configurations like Elasticsearch URLs and credentials in environment variables.
  4. 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!