Skip to content

Document Store: Use Cases

Document Store: Use Cases

Part of: HeliosDB Document Store User Guide

Use Case 1: Content Management System

Scenario: Blog platform with articles, authors, comments, and tags.

Schema:

// Articles collection
{
"_id": "article_123",
"title": "Introduction to HeliosDB",
"slug": "introduction-to-heliosdb",
"content": "HeliosDB is a next-generation database...",
"author": {
"id": "author_456",
"name": "Alice Smith",
"email": "alice@example.com"
},
"tags": ["database", "nosql", "tutorial"],
"status": "published",
"publishedAt": "2025-01-15T10:00:00Z",
"views": 1234,
"comments": [
{
"id": "comment_789",
"author": "Bob",
"text": "Great article!",
"createdAt": "2025-01-15T11:00:00Z"
}
],
"metadata": {
"readTime": 5,
"featured": true
}
}

Implementation:

use heliosdb_document::{DocumentStore, Collection, DocumentId, IndexDefinition, IndexType};
use serde_json::json;
// Initialize store
let store = DocumentStore::new("./cms_data")?;
let articles = Collection::new("articles");
// Create indexes
store.create_index(IndexDefinition {
name: "slug_idx".to_string(),
collection: articles.clone(),
index_type: IndexType::SingleField {
field: "slug".to_string(),
unique: true,
},
created_at: chrono::Utc::now(),
})?;
store.create_index(IndexDefinition {
name: "tags_idx".to_string(),
collection: articles.clone(),
index_type: IndexType::Multikey {
field: "tags".to_string(),
},
created_at: chrono::Utc::now(),
})?;
store.create_index(IndexDefinition {
name: "content_text_idx".to_string(),
collection: articles.clone(),
index_type: IndexType::Text {
fields: vec!["title".to_string(), "content".to_string()],
weights: {
let mut w = std::collections::HashMap::new();
w.insert("title".to_string(), 3.0);
w.insert("content".to_string(), 1.0);
w
},
},
created_at: chrono::Utc::now(),
})?;
// Insert article
let article = json!({
"title": "Introduction to HeliosDB",
"slug": "introduction-to-heliosdb",
"content": "HeliosDB is a next-generation multi-model database...",
"author": {
"id": "author_456",
"name": "Alice Smith",
"email": "alice@example.com"
},
"tags": ["database", "nosql", "tutorial"],
"status": "published",
"publishedAt": chrono::Utc::now().to_rfc3339(),
"views": 0,
"comments": []
});
store.insert(&articles, &DocumentId::new("article_123"), article)?;
// Query: Find articles by tag
let filter = Filter {
op: FilterOp::In {
field: "tags".to_string(),
values: vec![json!("database")],
},
};
let tagged_articles = store.find(&articles, filter)?;
// Query: Full-text search
// (Using MongoDB driver for text search)
let cursor = collection.find(doc! {
"$text": { "$search": "database tutorial" }
}, None).await?;
// Query: Get article by slug
let filter = Filter::eq("slug", json!("introduction-to-heliosdb"));
let article = store.find(&articles, filter)?.into_iter().next();
// Update: Increment view count
store.update(
&articles,
&DocumentId::new("article_123"),
json!({"views": article.unwrap().data["views"].as_i64().unwrap() + 1})
)?;
// Update: Add comment
let new_comment = json!({
"id": format!("comment_{}", uuid::Uuid::new_v4()),
"author": "Bob Johnson",
"text": "Great article!",
"createdAt": chrono::Utc::now().to_rfc3339()
});
// Get current comments and append
let article = store.get(&articles, &DocumentId::new("article_123"))?.unwrap();
let mut comments = article.data["comments"].as_array().unwrap().clone();
comments.push(new_comment);
store.update(
&articles,
&DocumentId::new("article_123"),
json!({"comments": comments})
)?;

Aggregation: Popular Tags:

use heliosdb_document::{AggregationStage, AggregationOp};
let pipeline = vec![
AggregationStage::Match {
filter: Filter::eq("status", json!("published")),
},
AggregationStage::Unwind {
field: "tags".to_string(),
preserve_null: false,
},
AggregationStage::Group {
id: Some(json!("$tags")),
fields: {
let mut fields = std::collections::HashMap::new();
fields.insert("count".to_string(), AggregationOp::Count);
fields
},
},
AggregationStage::Sort {
fields: vec![("count".to_string(), SortOrder::Desc)],
},
AggregationStage::Limit { count: 10 },
];
let popular_tags = store.aggregate(&articles, pipeline)?;
println!("Popular tags: {:?}", popular_tags);

Use Case 2: E-Commerce Product Catalog

Scenario: Product catalog with categories, variants, pricing, and inventory.

Schema:

{
"_id": "product_laptop_001",
"name": "UltraBook Pro 15",
"sku": "UBP15-256-16",
"description": "High-performance laptop for professionals",
"category": "Electronics > Computers > Laptops",
"brand": "TechCorp",
"price": {
"amount": 1299.99,
"currency": "USD",
"discounted": 1099.99,
"taxRate": 0.08
},
"variants": [
{
"sku": "UBP15-256-16-SLV",
"color": "Silver",
"storage": "256GB",
"memory": "16GB",
"price": 1299.99,
"stock": 15
},
{
"sku": "UBP15-512-32-BLK",
"color": "Black",
"storage": "512GB",
"memory": "32GB",
"price": 1699.99,
"stock": 8
}
],
"specifications": {
"processor": "Intel Core i7",
"display": "15.6\" 4K",
"weight": "1.8kg",
"battery": "10 hours"
},
"images": [
"https://cdn.example.com/laptop-001-front.jpg",
"https://cdn.example.com/laptop-001-side.jpg"
],
"ratings": {
"average": 4.5,
"count": 128
},
"tags": ["laptop", "ultrabook", "professional", "4k"],
"inStock": true,
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-01-15T10:00:00Z"
}

Implementation:

let store = DocumentStore::new("./ecommerce_data")?;
let products = Collection::new("products");
// Indexes for e-commerce
// 1. SKU (unique)
store.create_index(IndexDefinition {
name: "sku_idx".to_string(),
collection: products.clone(),
index_type: IndexType::SingleField {
field: "sku".to_string(),
unique: true,
},
created_at: chrono::Utc::now(),
})?;
// 2. Price range queries
store.create_index(IndexDefinition {
name: "price_idx".to_string(),
collection: products.clone(),
index_type: IndexType::SingleField {
field: "price.amount".to_string(),
unique: false,
},
created_at: chrono::Utc::now(),
})?;
// 3. Category navigation
store.create_index(IndexDefinition {
name: "category_idx".to_string(),
collection: products.clone(),
index_type: IndexType::SingleField {
field: "category".to_string(),
unique: false,
},
created_at: chrono::Utc::now(),
})?;
// 4. Full-text search
store.create_index(IndexDefinition {
name: "search_idx".to_string(),
collection: products.clone(),
index_type: IndexType::Text {
fields: vec![
"name".to_string(),
"description".to_string(),
"brand".to_string(),
],
weights: {
let mut w = std::collections::HashMap::new();
w.insert("name".to_string(), 3.0);
w.insert("brand".to_string(), 2.0);
w.insert("description".to_string(), 1.0);
w
},
},
created_at: chrono::Utc::now(),
})?;
// Query: Products in price range
let filter = Filter::and(vec![
Filter {
op: FilterOp::Gte {
field: "price.amount".to_string(),
value: json!(500.0),
},
},
Filter {
op: FilterOp::Lte {
field: "price.amount".to_string(),
value: json!(1500.0),
},
},
Filter::eq("inStock", json!(true)),
]);
let products_in_range = store.find(&products, filter)?;
// Query: Products by category
let filter = Filter {
op: FilterOp::Regex {
field: "category".to_string(),
pattern: "^Electronics > Computers".to_string(),
options: "i".to_string(),
},
};
let computers = store.find(&products, filter)?;
// Aggregation: Average price by category
let pipeline = vec![
AggregationStage::Group {
id: Some(json!("$category")),
fields: {
let mut fields = std::collections::HashMap::new();
fields.insert("avgPrice".to_string(), AggregationOp::Avg {
field: "price.amount".to_string(),
});
fields.insert("count".to_string(), AggregationOp::Count);
fields.insert("minPrice".to_string(), AggregationOp::Min {
field: "price.amount".to_string(),
});
fields.insert("maxPrice".to_string(), AggregationOp::Max {
field: "price.amount".to_string(),
});
fields
},
},
AggregationStage::Sort {
fields: vec![("avgPrice".to_string(), SortOrder::Desc)],
},
];
let category_stats = store.aggregate(&products, pipeline)?;

Inventory Management:

// Update stock when order placed
fn reduce_stock(
store: &DocumentStore,
product_id: &str,
variant_sku: &str,
quantity: i32,
) -> Result<()> {
let products = Collection::new("products");
let doc_id = DocumentId::new(product_id);
// Get current product
let product = store.get(&products, &doc_id)?.unwrap();
// Find variant and update stock
let mut variants = product.data["variants"].as_array().unwrap().clone();
for variant in &mut variants {
if variant["sku"].as_str() == Some(variant_sku) {
let current_stock = variant["stock"].as_i64().unwrap();
if current_stock < quantity as i64 {
return Err("Insufficient stock".into());
}
variant["stock"] = json!(current_stock - quantity as i64);
break;
}
}
// Update product
store.update(&products, &doc_id, json!({
"variants": variants,
"updatedAt": chrono::Utc::now().to_rfc3339()
}))?;
Ok(())
}

Use Case 3: User Profiles and Preferences

Scenario: User management system with profiles, preferences, activity tracking.

Schema:

{
"_id": "user_alice_123",
"username": "alice_smith",
"email": "alice@example.com",
"profile": {
"firstName": "Alice",
"lastName": "Smith",
"avatar": "https://cdn.example.com/avatars/alice.jpg",
"bio": "Software engineer and database enthusiast",
"location": {
"city": "San Francisco",
"state": "CA",
"country": "USA",
"coordinates": {
"type": "Point",
"coordinates": [-122.4194, 37.7749]
}
}
},
"preferences": {
"theme": "dark",
"language": "en",
"timezone": "America/Los_Angeles",
"notifications": {
"email": true,
"push": true,
"sms": false
},
"privacy": {
"profileVisibility": "public",
"showEmail": false,
"showLocation": true
}
},
"activity": {
"lastLogin": "2025-01-15T10:30:00Z",
"loginCount": 456,
"lastActive": "2025-01-15T14:20:00Z"
},
"roles": ["user", "premium"],
"tags": ["developer", "early-adopter"],
"metadata": {
"accountCreated": "2024-06-01T00:00:00Z",
"emailVerified": true,
"phoneVerified": false
}
}

Implementation:

let store = DocumentStore::new("./user_data")?;
let users = Collection::new("users");
// Schema validation
let schema = SchemaBuilder::new()
.title("User Schema")
.property("username", PropertyBuilder::string()
.min_length(3)
.max_length(20)
.pattern("^[a-zA-Z0-9_]+$")
.build())
.property("email", PropertyBuilder::string()
.format("email")
.build())
.property("profile", PropertyBuilder::object()
.property("firstName", PropertyBuilder::string().min_length(1).build())
.property("lastName", PropertyBuilder::string().min_length(1).build())
.build())
.required(vec!["username", "email", "profile"])
.build();
store.register_schema("users", schema)?;
// Indexes
// 1. Username (unique)
store.create_index(IndexDefinition {
name: "username_idx".to_string(),
collection: users.clone(),
index_type: IndexType::SingleField {
field: "username".to_string(),
unique: true,
},
created_at: chrono::Utc::now(),
})?;
// 2. Email (unique)
store.create_index(IndexDefinition {
name: "email_idx".to_string(),
collection: users.clone(),
index_type: IndexType::SingleField {
field: "email".to_string(),
unique: true,
},
created_at: chrono::Utc::now(),
})?;
// 3. Location (geospatial)
store.create_index(IndexDefinition {
name: "location_idx".to_string(),
collection: users.clone(),
index_type: IndexType::Geospatial {
field: "profile.location.coordinates".to_string(),
index_type: GeoIndexType::TwoDSphere,
},
created_at: chrono::Utc::now(),
})?;
// Create user
let user = json!({
"username": "alice_smith",
"email": "alice@example.com",
"profile": {
"firstName": "Alice",
"lastName": "Smith",
"bio": "Software engineer",
"location": {
"city": "San Francisco",
"state": "CA",
"country": "USA",
"coordinates": {
"type": "Point",
"coordinates": [-122.4194, 37.7749]
}
}
},
"preferences": {
"theme": "dark",
"language": "en",
"notifications": {
"email": true,
"push": true
}
},
"roles": ["user"],
"metadata": {
"accountCreated": chrono::Utc::now().to_rfc3339(),
"emailVerified": false
}
});
store.insert(&users, &DocumentId::new("user_alice_123"), user)?;
// Update preferences
fn update_preferences(
store: &DocumentStore,
user_id: &str,
prefs: serde_json::Value,
) -> Result<()> {
store.update(
&Collection::new("users"),
&DocumentId::new(user_id),
json!({"preferences": prefs})
)?;
Ok(())
}
// Track login
fn track_login(store: &DocumentStore, user_id: &str) -> Result<()> {
let users = Collection::new("users");
let doc_id = DocumentId::new(user_id);
let user = store.get(&users, &doc_id)?.unwrap();
let login_count = user.data["activity"]["loginCount"].as_i64().unwrap_or(0);
store.update(&users, &doc_id, json!({
"activity": {
"lastLogin": chrono::Utc::now().to_rfc3339(),
"loginCount": login_count + 1,
"lastActive": chrono::Utc::now().to_rfc3339()
}
}))?;
Ok(())
}
// Find nearby users (geospatial)
// (Using MongoDB driver)
let nearby = collection.find(doc! {
"profile.location.coordinates": {
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [-122.4194, 37.7749] // SF
},
"$maxDistance": 10000 // 10km
}
}
}, None).await?;

Use Case 4: Event Logging and Analytics

Scenario: Application event logging with real-time analytics.

Schema:

{
"_id": "event_12345",
"eventType": "page_view",
"timestamp": "2025-01-15T14:30:00Z",
"user": {
"id": "user_456",
"sessionId": "session_789"
},
"page": {
"url": "/products/laptop-001",
"title": "UltraBook Pro 15",
"referrer": "https://google.com"
},
"device": {
"type": "desktop",
"os": "macOS",
"browser": "Chrome",
"screenResolution": "1920x1080"
},
"location": {
"country": "USA",
"region": "California",
"city": "San Francisco",
"ip": "192.168.1.100"
},
"metadata": {
"duration": 45, // seconds
"scrollDepth": 75 // percent
}
}

Implementation:

let store = DocumentStore::new("./events_data")?;
let events = Collection::new("events");
// Indexes optimized for time-series queries
// 1. Timestamp (for time-range queries)
store.create_index(IndexDefinition {
name: "timestamp_idx".to_string(),
collection: events.clone(),
index_type: IndexType::SingleField {
field: "timestamp".to_string(),
unique: false,
},
created_at: chrono::Utc::now(),
})?;
// 2. Event type + timestamp (compound)
store.create_index(IndexDefinition {
name: "type_time_idx".to_string(),
collection: events.clone(),
index_type: IndexType::Compound {
fields: vec!["eventType".to_string(), "timestamp".to_string()],
unique: false,
},
created_at: chrono::Utc::now(),
})?;
// 3. User ID (for user analytics)
store.create_index(IndexDefinition {
name: "user_idx".to_string(),
collection: events.clone(),
index_type: IndexType::SingleField {
field: "user.id".to_string(),
unique: false,
},
created_at: chrono::Utc::now(),
})?;
// Log event
fn log_event(
store: &DocumentStore,
event_type: &str,
user_id: &str,
data: serde_json::Value,
) -> Result<()> {
let event = json!({
"eventType": event_type,
"timestamp": chrono::Utc::now().to_rfc3339(),
"user": {
"id": user_id
},
"data": data
});
store.insert(
&Collection::new("events"),
&DocumentId::new(&format!("event_{}", uuid::Uuid::new_v4())),
event
)?;
Ok(())
}
// Real-time analytics aggregation
use heliosdb_document::{AggregationStage, AggregationOp};
// Events per hour (last 24 hours)
let pipeline = vec![
AggregationStage::Match {
filter: Filter {
op: FilterOp::Gte {
field: "timestamp".to_string(),
value: json!(
(chrono::Utc::now() - chrono::Duration::hours(24))
.to_rfc3339()
),
},
},
},
AggregationStage::Group {
id: Some(json!({
"hour": { "$hour": "$timestamp" },
"type": "$eventType"
})),
fields: {
let mut fields = std::collections::HashMap::new();
fields.insert("count".to_string(), AggregationOp::Count);
fields
},
},
AggregationStage::Sort {
fields: vec![
("_id.hour".to_string(), SortOrder::Asc),
("count".to_string(), SortOrder::Desc),
],
},
];
let hourly_stats = store.aggregate(&events, pipeline)?;
// Top pages by views
let pipeline = vec![
AggregationStage::Match {
filter: Filter::eq("eventType", json!("page_view")),
},
AggregationStage::Group {
id: Some(json!("$page.url")),
fields: {
let mut fields = std::collections::HashMap::new();
fields.insert("views".to_string(), AggregationOp::Count);
fields.insert("avgDuration".to_string(), AggregationOp::Avg {
field: "metadata.duration".to_string(),
});
fields
},
},
AggregationStage::Sort {
fields: vec![("views".to_string(), SortOrder::Desc)],
},
AggregationStage::Limit { count: 10 },
];
let top_pages = store.aggregate(&events, pipeline)?;
// User journey (session replay)
let filter = Filter::eq("user.sessionId", json!("session_789"));
let session_events = store.find(&events, filter)?;
// Sort by timestamp
let mut events_sorted = session_events;
events_sorted.sort_by(|a, b| {
a.data["timestamp"]
.as_str()
.cmp(&b.data["timestamp"].as_str())
});

Use Case 5: Mobile App Backend

Scenario: Offline-first mobile app with sync.

Schema:

{
"_id": "note_uuid_123",
"userId": "user_456",
"title": "Meeting Notes",
"content": "Discussed Q1 roadmap...",
"tags": ["work", "meeting"],
"attachments": [
{
"id": "attach_789",
"filename": "roadmap.pdf",
"url": "https://cdn.example.com/files/roadmap.pdf",
"size": 1024000
}
],
"metadata": {
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T14:30:00Z",
"deviceId": "device_mobile_001",
"version": 3, // For conflict resolution
"synced": true
}
}

Implementation:

// Mobile app: Store locally and sync
use heliosdb_document::{DocumentStore, Collection, DocumentId};
let store = DocumentStore::new("./mobile_data")?;
let notes = Collection::new("notes");
// Create note offline
fn create_note_offline(
store: &DocumentStore,
user_id: &str,
title: &str,
content: &str,
) -> Result<String> {
let note_id = format!("note_{}", uuid::Uuid::new_v4());
let note = json!({
"userId": user_id,
"title": title,
"content": content,
"tags": [],
"metadata": {
"createdAt": chrono::Utc::now().to_rfc3339(),
"updatedAt": chrono::Utc::now().to_rfc3339(),
"version": 1,
"synced": false // Not yet synced
}
});
store.insert(
&Collection::new("notes"),
&DocumentId::new(&note_id),
note
)?;
Ok(note_id)
}
// Sync to server
async fn sync_to_server(store: &DocumentStore) -> Result<()> {
let notes = Collection::new("notes");
// Find unsynced notes
let filter = Filter::eq("metadata.synced", json!(false));
let unsynced = store.find(&notes, filter)?;
for note in unsynced {
// Upload to server
let response = upload_to_server(&note.data).await?;
// Mark as synced
store.update(
&notes,
&note.metadata.id,
json!({"metadata": {"synced": true}})
)?;
}
Ok(())
}
// Conflict resolution (last-write-wins with version)
fn merge_note(
store: &DocumentStore,
note_id: &str,
local_note: &Document,
server_note: &serde_json::Value,
) -> Result<()> {
let local_version = local_note.data["metadata"]["version"].as_i64().unwrap();
let server_version = server_note["metadata"]["version"].as_i64().unwrap();
if server_version > local_version {
// Server is newer, update local
store.update(
&Collection::new("notes"),
&DocumentId::new(note_id),
server_note.clone()
)?;
} else if local_version > server_version {
// Local is newer, push to server
upload_to_server(&local_note.data).await?;
}
// If equal, no action needed
Ok(())
}

Use Case 6: Real-Time Collaboration

Scenario: Collaborative document editing (like Google Docs).

Schema:

{
"_id": "doc_collaborative_123",
"title": "Project Proposal",
"owner": "user_alice",
"collaborators": [
{
"userId": "user_bob",
"role": "editor",
"addedAt": "2025-01-10T00:00:00Z"
},
{
"userId": "user_carol",
"role": "viewer",
"addedAt": "2025-01-12T00:00:00Z"
}
],
"content": {
"blocks": [
{
"id": "block_1",
"type": "heading",
"text": "Introduction",
"version": 5
},
{
"id": "block_2",
"type": "paragraph",
"text": "This proposal outlines...",
"version": 12
}
]
},
"activeEditors": [
{
"userId": "user_bob",
"cursor": {
"blockId": "block_2",
"position": 45
},
"lastActive": "2025-01-15T14:30:00Z"
}
],
"version": 17,
"metadata": {
"createdAt": "2025-01-10T00:00:00Z",
"updatedAt": "2025-01-15T14:30:00Z"
}
}

Implementation:

// Change streams for real-time updates
let mut stream = store.watch(Collection::new("documents"))?;
// Broadcast changes to all connected clients
tokio::spawn(async move {
while let Some(event) = stream.next().await.unwrap() {
match event.event_type {
ChangeEventType::Update => {
if let Some(desc) = event.update_description {
// Broadcast to WebSocket clients
let update_msg = json!({
"type": "document_update",
"documentId": event.document_id.as_str(),
"changes": desc.updated_fields,
"version": desc.updated_fields.get("version")
});
broadcast_to_collaborators(
event.document_id.as_str(),
update_msg
).await;
}
}
_ => {}
}
}
});
// Update document block
fn update_block(
store: &DocumentStore,
doc_id: &str,
block_id: &str,
new_text: &str,
) -> Result<()> {
let docs = Collection::new("documents");
let doc_id_obj = DocumentId::new(doc_id);
// Get document
let doc = store.get(&docs, &doc_id_obj)?.unwrap();
// Update specific block
let mut blocks = doc.data["content"]["blocks"].as_array().unwrap().clone();
for block in &mut blocks {
if block["id"].as_str() == Some(block_id) {
block["text"] = json!(new_text);
let version = block["version"].as_i64().unwrap();
block["version"] = json!(version + 1);
break;
}
}
// Update document
let doc_version = doc.data["version"].as_i64().unwrap();
store.update(&docs, &doc_id_obj, json!({
"content": {
"blocks": blocks
},
"version": doc_version + 1,
"metadata": {
"updatedAt": chrono::Utc::now().to_rfc3339()
}
}))?;
Ok(())
}
// Track active editors
fn update_cursor(
store: &DocumentStore,
doc_id: &str,
user_id: &str,
block_id: &str,
position: i32,
) -> Result<()> {
let docs = Collection::new("documents");
let doc_id_obj = DocumentId::new(doc_id);
let doc = store.get(&docs, &doc_id_obj)?.unwrap();
// Update active editors list
let mut editors = doc.data["activeEditors"].as_array().unwrap().clone();
let mut found = false;
for editor in &mut editors {
if editor["userId"].as_str() == Some(user_id) {
editor["cursor"] = json!({
"blockId": block_id,
"position": position
});
editor["lastActive"] = json!(chrono::Utc::now().to_rfc3339());
found = true;
break;
}
}
if !found {
editors.push(json!({
"userId": user_id,
"cursor": {
"blockId": block_id,
"position": position
},
"lastActive": chrono::Utc::now().to_rfc3339()
}));
}
store.update(&docs, &doc_id_obj, json!({
"activeEditors": editors
}))?;
Ok(())
}


Navigation: ← Previous: Change Streams | Back to Index | Next: Performance Optimization →