Search

Connect to Elasticsearch

elasticsearch elasticsearch-crates.io elasticsearch-github elasticsearch-lib.rs cat-api-bindings cat-database

use elasticsearch::BulkParts;
use elasticsearch::Elasticsearch;
use elasticsearch::Error;
use elasticsearch::IndexParts;
use elasticsearch::SearchParts;
use elasticsearch::cat::CatIndicesParts;
use elasticsearch::http::request::JsonBody;
use elasticsearch::http::response::Response;
use elasticsearch::http::transport::Transport;
use serde::Deserialize;
use serde::Serialize;
use serde_json::Value;

#[derive(Debug, Serialize, Deserialize)]
struct MyDocument {
    id: i32,
    title: String,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Create an asynchronous Elasticsearch client
    let url = std::env::var("ELASTIC_URL")
        .unwrap_or_else(|_| "http://localhost:9200".into());
    let transport = Transport::single_node(&url)?;
    let client = Elasticsearch::new(transport);
    // OR: let client = Elasticsearch::default();

    let response: Response = index_document(&client).await?;
    println!("Index response: {:?}", response);

    let search_result: serde_json::Value = search_document(&client).await?;
    println!("Search result: {:?}", search_result);

    let bulk_response: bool = bulk_documents(&client).await?;
    println!("Bulk response: {:?}", bulk_response);

    cat_indices(client).await?;

    Ok(())
}

// Create (or update) a document in an index.
async fn index_document(client: &Elasticsearch) -> Result<Response, Error> {
    // Define a document to index
    let doc = MyDocument {
        id: 1,
        title: "Rust with Elasticsearch".to_string(),
    };
    // Index the document
    let response = client
        .index(IndexParts::IndexId("my_index", "1"))
        .body(serde_json::json!(doc))
        .send()
        .await?;
    Ok(response)
}

//
async fn search_document(
    client: &Elasticsearch,
) -> Result<serde_json::Value, Error> {
    // Search for the document
    let search_response = client
        .search(SearchParts::Index(&["my_index"]))
        .from(0)
        .size(10)
        .body(serde_json::json!({
            "query": {
                "match": {
                    "title": "Rust"
                }
            }
        }))
        .send()
        .await?;
    let search_result = search_response.json::<serde_json::Value>().await?;
    Ok(search_result)
}

// Interact with an Elasticsearch client to perform bulk indexing operations.
async fn bulk_documents(client: &Elasticsearch) -> anyhow::Result<bool> {
    let mut body: Vec<JsonBody<_>> = Vec::with_capacity(4);

    // Add the first operation and document
    body.push(serde_json::json!({"index": {"_id": "1"}}).into());
    body.push(
        serde_json::json!({
            "id": 1,
            "user": "user1",
            "post_date": "2025-02-06T00:00:00Z",
            "message": "Trying out Elasticsearch"
        })
        .into(),
    );

    // Add the second operation and document
    body.push(serde_json::json!({"index": {"_id": "2"}}).into());
    body.push(
        serde_json::json!({
            "id": 2,
            "user": "user2",
            "post_date": "2025-02-07T00:00:00Z",
            "message": "Bulk indexing with the rust client!"
        })
        .into(),
    );

    let response = client
        .bulk(BulkParts::Index("tweets"))
        .body(body)
        .send()
        .await?;

    let response_body = response.json::<Value>().await?;
    let successful =
        !(response_body["errors"].as_bool().ok_or(anyhow::anyhow!(
            "bulk_documents: response could not be converted to bool"
        ))?);

    Ok(successful)
}

async fn cat_indices(client: Elasticsearch) -> Result<Response, Error> {
    // Call the `Cat` related APIs.
    let response = client
        .cat()
        .indices(CatIndicesParts::Index(&["*"]))
        .format("json")
        .send()
        .await?;
    Ok(response)
}

Add a Full-text Search Engine to a Static Website

tinysearch tinysearch-crates.io tinysearch-github tinysearch-lib.rs

tinysearch is a lightweight, fast, full-text search engine. It is designed for static websites.

tinysearch is compiled to WebAssembly to run in a browser. It can be used together with static site generators such as Jekyll, Hugo, Zola, Cobalt, or Pelican.