OpenSearch Client for Rust
A comprehensive Rust client library for OpenSearch with a strongly typed DSL, CLI tools, and extensive API coverage.
๐ Features
- Strongly Typed DSL: Type-safe query building with compile-time guarantees
- Comprehensive API Coverage: Support for search, indices, cluster management, and more
- CLI Tools: Command-line interface for cluster management and data operations
- Async/Await Support: Built on modern async Rust with tokio
- Production Ready: Includes retry logic, connection pooling, and error handling
- Extensible: Modular design with feature flags for optional functionality
๐ฆ Project Structure
This workspace contains several crates:
opensearch-client: Core client library with API bindingsopensearch-dsl: Strongly typed query DSLopensearch-cli: Command-line tools for cluster managementopensearch-testcontainer: Testing utilities with container support
๐ Installation
Add the dependencies to your Cargo.toml:
[]
= "0.3"
= "0.3"
The macro support is included by default - no additional features needed!
๐ง Quick Start
Basic Client Usage
use ;
use Url;
async
Query Building with DSL
use *;
let query = new
.source
.from
.size
.query
.aggregations;
// Execute the search
let response = client.search.index.await?;
Document Modeling with Macros
The opensearch-client provides a powerful macro system for creating strongly-typed document models that automatically implement the Document trait.
Quick Navigation:
- Basic Document Definition
- Working with Documents
- CRUD Operations
- Querying and Search
- Field Type Mapping
- Macro Attributes
- Field Introspection
- Nested Documents
- Best Practices
- API Reference
Basic Document Definition
use ;
use ;
Working with Document Models
Once you've defined your models, you can use them with full type safety:
async
Document Trait Features
The Document trait provides a comprehensive API for working with OpenSearch documents:
Core Methods
// Get index name and field metadata
let index = index_name; // "users"
let fields = columns; // Vec<Field> with type info
// Instance methods
let user = get.await?;
let user_id = user.id; // Get document ID
CRUD Operations
// Create/Update
let response = user.save.await?;
// Read
let user = get.await?;
let maybe_user = find_one.await?;
// Update with partial data
update.await?;
// Refresh instance from database
user.refresh.await?;
// Delete
delete.await?;
Querying and Search
// Find with complex queries
let results = find.await?;
// Find all documents
let all_users = find_all.await?;
// Count documents
let active_count = count.await?;
let total_count = count.await?;
Field Type Mapping
The macro automatically maps Rust types to OpenSearch field types:
| Rust Type | OpenSearch Type | Field Type | Notes |
|---|---|---|---|
String, &str |
text |
string |
Full-text searchable |
u32, i32, u64, i64 |
long |
number |
Aggregatable, sortable |
f32, f64 |
double |
number |
Aggregatable, sortable |
bool |
boolean |
boolean |
Aggregatable, sortable |
Vec<T> |
(inner type) | (inner type) | Arrays of the inner type |
Option<T> |
(inner type) | (inner type) | Nullable fields |
| Custom structs | object |
object |
Nested documents |
Macro Attributes
Index Configuration
// Required: specify the index name
ID Field
The ID field must be of type String and will be used as the document's unique identifier in OpenSearch.
Field Introspection
The generated columns() method provides detailed field metadata:
let fields = columns;
for field in fields
This metadata can be used for:
- Dynamic query building
- Index mapping generation
- API documentation
- Query validation
Nested Documents
When using custom types as fields, the macro recognizes them as nested documents:
// The UserProfile fields are accessible through its own columns() method
let profile_fields = columns;
This enables complex document structures while maintaining type safety and field introspection capabilities.
Best Practices
Required Derives
Always include these derives for full functionality:
Debug- For debugging and loggingClone- Required by the Document traitSerialize/Deserialize- For JSON conversion with serdeOpenSearch- The derive macro that implements Document
ID Field Guidelines
- The ID field must be of type
String - Exactly one field must be marked with
#[os(id)] - The ID field is used for document identification in OpenSearch
Index Naming
// Good: lowercase, descriptive
// Good: snake_case for multi-word
// Good: kebab-case alternative
- Use lowercase names
- Avoid special characters except hyphens and underscores
- Choose descriptive, consistent naming patterns
Type Compatibility
// Supported primitive types
Index Management
// Create an index
client.indices
.create
.mappings
.await?;
// Index a document
client.index
.id
.body
.await?;
๐ฅ CLI Tools
The project includes a powerful CLI tool for cluster management:
# Install the CLI
# List all indices
# Dump cluster metadata
# Restore metadata
# Copy index between clusters
CLI Configuration
Set environment variables or use command-line flags:
# Or use flags
๐ Architecture
Client Library (opensearch-client)
The core client provides:
- HTTP Transport: Built on reqwest with middleware support
- Authentication: Basic auth, API keys, and custom auth
- API Modules: Organized by OpenSearch API categories
- Error Handling: Comprehensive error types and retry logic
- Connection Management: Connection pooling and keep-alive
DSL Library (opensearch-dsl)
The DSL provides type-safe query building:
- Query Types: Match, term, bool, range, and more
- Aggregations: Bucket, metric, and pipeline aggregations
- Response Parsing: Strongly typed response structures
- Validation: Compile-time query validation
CLI Tools (opensearch-cli)
Command-line utilities for:
- Metadata Management: Index templates, pipelines, components
- Data Operations: Dump, restore, and copy indices
- Cluster Management: Health checks and monitoring
- Remote Operations: Multi-cluster support
๐ง Configuration
Client Configuration
use ConfigurationBuilder;
let config = new
.base_url
.basic_auth
.timeout
.retry_attempts
.build;
Feature Flags
Enable only the features you need:
[]
= { = "0.3", = [
"search",
"indices",
"cluster",
"ml"
] }
Available features:
search- Search APIs (default)indices- Index management (default)cluster- Cluster APIs (default)ml- Machine learning APIs (default)security- Security APIstools- Utility tools
๐ Examples
Bulk Operations
use *;
let mut bulk = new;
bulk.index;
bulk.index;
bulk.delete;
let response = client.bulk.await?;
Document Modeling Examples
use ;
use ;
// Blog post with tags and metadata
// Example of a non-Document struct for complex data
// Using the models
async
Aggregations
let search = new
.aggregations;
Stream Processing
let mut stream = client.search_stream.index.scroll;
while let Some = stream.next.await
๐ Document Trait API Reference
The Document trait provides a complete ORM-like interface for working with OpenSearch documents. All methods are automatically implemented when you use the #[derive(OpenSearch)] macro.
Static Methods
| Method | Signature | Description |
|---|---|---|
index_name() |
fn index_name() -> &'static str |
Returns the index name configured with #[os(index = "...")] |
columns() |
fn columns() -> Vec<Field> |
Returns field metadata for introspection and mapping |
get(id) |
async fn get(id: &str) -> Result<Self, Error> |
Fetch a document by ID |
delete(id) |
async fn delete(id: &str) -> Result<DocumentDeleteResponse, Error> |
Delete a document by ID |
update(id, doc) |
async fn update(id: &str, partial_doc: &Value) -> Result<IndexResponse, Error> |
Update document with partial data |
find(search) |
async fn find(search: Search) -> Result<TypedSearchResult<Self>, Error> |
Search with custom query |
find_all(limit) |
async fn find_all(limit: Option<usize>) -> Result<TypedSearchResult<Self>, Error> |
Find all documents with optional limit |
find_one(search) |
async fn find_one(search: Search) -> Result<Option<Self>, Error> |
Find single document matching query |
count(query) |
async fn count(query: Option<Query>) -> Result<u32, Error> |
Count documents matching query |
Instance Methods
| Method | Signature | Description |
|---|---|---|
id() |
fn id(&self) -> &str |
Get the document's ID (from field marked with #[os(id)]) |
save() |
async fn save(&self) -> Result<IndexResponse, Error> |
Create or update this document |
refresh() |
async fn refresh(&mut self) -> Result<(), Error> |
Reload this instance from OpenSearch |
Field Metadata
The Field struct returned by columns() contains:
๐งช Testing
Run the test suite:
# Unit tests
# Integration tests (requires OpenSearch running)
# Test with specific OpenSearch version
๐ค Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
- Clone the repository:
- Install dependencies:
- Run tests:
- Start OpenSearch for integration tests:
๐ License
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
๐ Related Projects
- OpenSearch - The OpenSearch search engine
- elasticsearch-dsl-rs - Original Elasticsearch DSL inspiration
- opensearch-rs - Alternative Rust client
๐ Support
Made with โค๏ธ by the OpenSearch Rust community