dream_opensearch
Simple OpenSearch client for Gleam.
A standalone HTTP client for interacting with OpenSearch (or Elasticsearch) clusters. Provides clean interfaces for indexing, searching, and managing documents. Built with the same quality standards as Dream, but completely independent—use it in any Gleam project.
Features
- ✅ Document indexing and deletion
- ✅ Full-text search
- ✅ Index management
- ✅ Bulk operations
- ✅ Query builder helpers
- ✅ Zero dependencies on Dream or other frameworks
Installation
gleam add dream_opensearch
Quick Start
import dream_opensearch/client
import dream_opensearch/document
import dream_opensearch/query
import gleam/json
// Create client
let client = client.new("http://localhost:9200")
// Index a document
let doc = json.object([
#("name", json.string("Alice")),
#("email", json.string("alice@example.com")),
])
document.index(client, "users", "123", json.to_string(doc))
// Search documents
let search_query = query.match("name", "Alice")
case document.search(client, "users", search_query) {
Ok(results) -> process_results(results)
Error(msg) -> handle_error(msg)
}
// Delete document
document.delete(client, "users", "123")
Usage
Client Setup
import dream_opensearch/client
// Basic setup
let client = client.new("http://localhost:9200")
// With authentication
let client = client.new("https://user:pass@search.example.com:9200")
Indexing Documents
import dream_opensearch/document
import gleam/json
let doc = json.object([
#("name", json.string("Alice")),
#("email", json.string("alice@example.com")),
#("age", json.int(30)),
])
case document.index(client, "users", "123", json.to_string(doc)) {
Ok(response) -> io.println("Indexed successfully")
Error(msg) -> io.println("Error: " <> msg)
}
Searching
Use query builders for common queries:
import dream_opensearch/document
import dream_opensearch/query
// Full-text search
let query = query.match("name", "Alice")
document.search(client, "users", query)
// Exact term match
let query = query.term("status", "active")
document.search(client, "users", query)
// Range query
let query = query.range("age", "18", "65")
document.search(client, "users", query)
// Match all
let query = query.match_all()
document.search(client, "users", query)
Custom Queries
For complex queries, build JSON manually:
import gleam/json
let query = json.object([
#("query", json.object([
#("bool", json.object([
#("must", json.array([
json.object([#("match", json.object([#("name", json.string("Alice"))]))]),
])),
#("filter", json.array([
json.object([#("term", json.object([#("status", json.string("active"))]))]),
])),
])),
])),
])
document.search(client, "users", json.to_string(query))
Index Management
import dream_opensearch/document
import gleam/json
// Create index with mapping
let mapping = json.object([
#("mappings", json.object([
#("properties", json.object([
#("name", json.object([#("type", json.string("text"))])),
#("email", json.object([#("type", json.string("keyword"))])),
])),
])),
])
document.create_index(client, "users", json.to_string(mapping))
// Delete index
document.delete_index(client, "old_index")
Bulk Operations
import dream_opensearch/document
// NDJSON format: action and document on alternating lines
let ndjson = "{ \"index\": { \"_index\": \"users\", \"_id\": \"1\" } }\n"
<> "{ \"name\": \"Alice\", \"email\": \"alice@example.com\" }\n"
<> "{ \"index\": { \"_index\": \"users\", \"_id\": \"2\" } }\n"
<> "{ \"name\": \"Bob\", \"email\": \"bob@example.com\" }\n"
document.bulk(client, ndjson)
API Reference
Client
client.new(base_url)- Create new OpenSearch client
Document Operations
document.index(client, index, id, json)- Index a documentdocument.search(client, index, query_json)- Search documentsdocument.delete(client, index, id)- Delete a documentdocument.create_index(client, index, mapping_json)- Create indexdocument.delete_index(client, index)- Delete indexdocument.bulk(client, ndjson)- Bulk index documents
Query Builders
query.match_all()- Match all documentsquery.match(field, text)- Full-text searchquery.term(field, value)- Exact term matchquery.range(field, gte, lte)- Range query
Design Principles
This module follows the same quality standards as Dream:
- No nested cases - Clear, flat control flow
- No anonymous functions - Named functions for clarity
- Builder pattern - Consistent, composable APIs
- Type safety -
Resulttypes force error handling - Quality testing - Comprehensive test coverage
About Dream
This module was originally built for the Dream web toolkit, but it’s completely standalone and can be used in any Gleam project. It follows Dream’s design principles and will be maintained as part of the Dream ecosystem.
License
MIT License - see LICENSE file for details.