Skip to main content

Crate rustlavel_search

Crate rustlavel_search 

Source
Expand description

rustlavel-search: Elasticsearch and OpenSearch.

One package serves both. OpenSearch was forked from Elasticsearch 7.10 and the two have not diverged on anything this crate touches: _search, _bulk, _doc, _mapping, _refresh and _cluster/health take the same bodies and answer with the same shapes on either. Nothing here prefers one. ClusterInfo::distribution says which one answered, for the rare caller that has to branch on it.

There is no protocol to write here — the cluster speaks HTTP and JSON, and the framework already has both. What this crate is actually for is the things that go wrong:

  • _bulk answers 200 when documents were lost. Per-item failures live in the body, and a caller that checks the status writes a loader that silently drops rows. See BulkReport.
  • The total on a search is a floor, not a count. Counting stops at 10,000 by default. See TotalHits.
  • A search can succeed on some shards and fail on others, answering 200 with fewer results and no other sign. See SearchResults::is_partial.
  • A document is not searchable the moment it is written. See SearchClient::refresh.
  • Failures need telling apart. A rejected write is worth repeating; a document that does not fit the mapping never is. See SearchError.
ⓘ
let client = SearchClient::new("http://localhost:9200").basic_auth("elastic", &password);

client
    .create_index_if_missing(
        "posts",
        &IndexDefinition::new()
            .field("title", Field::text().with_keyword())
            .field("tags", Field::keyword())
            .field("views", Field::long())
            .dynamic_strict(),
    )
    .await?;

client.bulk("posts", &operations).await?.ok_or_error()?;
client.refresh("posts").await?;

let results = client
    .search(
        "posts",
        &Search::new()
            .query(
                Query::bool()
                    .must(Query::matching("title", "rust").and())
                    .filter(Query::range("views").gte(100)),
            )
            .aggregate("by_tag", Aggregation::terms("tags").size(10))
            .track_total_hits(true),
    )
    .await?;

println!("{} matches", results.total);

Tests need no cluster: SearchClient::faking is Http::fake(), and the integration tests under tests/ run against a real server only when ELASTICSEARCH_URL is set.

Re-exports§

pub use client::ClusterHealth;
pub use client::ClusterInfo;
pub use client::HealthStatus;
pub use client::SearchClient;
pub use document::BulkItem;
pub use document::BulkOperation;
pub use document::BulkReport;
pub use document::Document;
pub use document::IndexedDocument;
pub use document::WriteResult;
pub use error::Result;
pub use error::SearchError;
pub use index::Field;
pub use index::IndexDefinition;
pub use logs::LogSettings;
pub use logs::LogShipper;
pub use logs::LogShipping;
pub use logs::LogStats;
pub use query::Aggregation;
pub use query::BoolQuery;
pub use query::Match;
pub use query::Order;
pub use query::Query;
pub use query::Range;
pub use query::Search;
pub use response::Aggregations;
pub use response::Bucket;
pub use response::Hit;
pub use response::SearchResults;
pub use response::Shards;
pub use response::StatsResult;
pub use response::TermsResult;
pub use response::TotalHits;
pub use response::TotalRelation;

Modules§

client
Talking to Elasticsearch or OpenSearch.
document
Writing and reading documents.
error
What a cluster says when it says no.
index
Creating indices and describing what goes in them.
logs
Shipping logs to Elasticsearch or OpenSearch.
prelude
Everything an application normally needs, in one import.
query
Building a query without writing the DSL by hand.
response
Reading a search response.