Skip to main content

Collections & Schemas

Collections are containers for your data, similar to tables in traditional databases. Each collection can have an optional schema that enforces data structure, types, and validation rules.

:::tip Collection vs Schema

  • Collection - The data container itself
  • Schema - The validation rules and structure definition for that collection :::

Create Collection

Create a new collection with optional schema validation.

:::danger Admin Permission Required Creating collections requires admin permissions. :::

use std::collections::HashMap;

client.create_collection(
"users",
Some(Schema {
fields: [
("name".to_string(), FieldSchema { field_type: "String", required: true, ..Default::default() }),
("email".to_string(), FieldSchema { field_type: "String", required: true, ..Default::default() }),
("age".to_string(), FieldSchema { field_type: "Number", required: false, ..Default::default() }),
].into_iter().collect(),
})
).await?;

Get Collection Info

Retrieve metadata about a collection.

let info = client.get_collection_info("users").await?;

println!("Records: {}", info.record_count);
println!("Schema: {:?}", info.schema);

List All Collections

Get a list of all collections in the database.

:::danger Admin Permission Required Listing all collections requires admin permissions. :::

let collections = client.list_collections().await?;

println!("{:?}", collections);

Delete Collection

Delete an entire collection and all its records permanently.

:::danger Warning This operation requires Admin access and is irreversible. Use with extreme caution. :::

client.delete_collection("users").await?;

Restore Record from Trash

Restore a previously deleted record from trash. Records remain in trash for 30 days before permanent deletion.

:::danger Admin Permission Required Restoring records from trash requires admin permissions. :::

client.restore_from_trash("users", &record_id).await?;

Restore Collection from Trash

Restore all deleted records in a collection from trash.

:::danger Admin Permission Required Restoring collections from trash requires admin permissions. :::

let result = client.restore_collection_from_trash("users").await?;

println!("Restored: {} records", result.records_restored);

:::tip Trash Retention Deleted records are kept in trash for 30 days. After this period, they are permanently deleted and cannot be restored. :::

Get Schema

Retrieve the current schema for a collection.

let schema = client.get_schema("users").await?;

println!("{:?}", schema.fields);

Update Schema Constraints

Update validation constraints for an existing schema.

:::danger Admin Permission Required Updating schema constraints requires admin permissions. :::

client.update_schema("users", Schema {
fields: [
("email".to_string(), FieldSchema {
field_type: "String",
required: true,
..Default::default()
}),
("age".to_string(), FieldSchema {
field_type: "Integer",
min: Some(18),
max: Some(100),
..Default::default()
}),
].into_iter().collect(),
}).await?;

:::warning Schema Updates Schema updates only affect new records. Existing records are not automatically migrated or validated against the new schema. :::

Set Primary Key Alias

Configure a custom field to use as the primary key instead of the default id.

:::danger Admin Permission Required Setting a primary key alias requires admin permissions. :::

client.set_primary_key_alias("products", "sku").await?;

Example - Using Custom Primary Key:

use ekodb_client::Record;

// Insert with custom primary key
let mut user = Record::new();
user.insert("user_id", "custom_user_001");
user.insert("name", "John Doe");
user.insert("email", "john@example.com");

let result = client.insert("users", user).await?;

// Retrieve using custom primary key
let user = client.find_by_id("users", "custom_user_001").await?;
println!("Found user: {:?}", user);

Schema Field Types

Supported Data Types

TypeDescriptionValidation Options
StringText valuesmax_length, min_length, pattern
Integer64-bit signed integersmin, max
Float64-bit floating-point numbersmin, max
NumberIntegers and floatsmin, max
BooleanTrue/false valuesNone
ArrayLists of valuesitems, min_items, max_items
ObjectNested JSON objectsproperties
DateTimeRFC 3339 datetime stringsformat
DecimalArbitrary-precision decimalsmin, max
UUIDRFC 4122 identifiersNone
VectorNumeric arrays for embeddingsNone
SetUnique value collectionsmin_items, max_items
BinaryBase64-encoded binary dataNone
BytesRaw byte arraysNone
DurationTime span valuesNone

Field Constraints

String Constraints:

{
"username": {
"type": "String",
"required": true,
"min_length": 3,
"max_length": 20,
"pattern": "^[a-zA-Z0-9_]+$"
}
}

Number Constraints:

{
"age": {
"type": "Number",
"min": 0,
"max": 150
},
"price": {
"type": "Number",
"min": 0.01,
"max": 999999.99
}
}

Array Constraints:

{
"tags": {
"type": "Array",
"items": {
"type": "String",
"max_length": 50
},
"min_items": 1,
"max_items": 10
}
}

Enum Validation:

{
"status": {
"type": "String",
"enum": ["draft", "published", "archived"],
"default": "draft"
}
}

Nested Objects:

{
"address": {
"type": "Object",
"properties": {
"street": {
"type": "String",
"required": true
},
"city": {
"type": "String",
"required": true
},
"postal_code": {
"type": "String",
"pattern": "^[0-9]{5}$"
}
}
}
}

Complete Example

Here's a complete workflow for creating and managing a collection:

#!/bin/bash

# 1. Create collection with schema
curl -X POST https://{EKODB_API_URL}/api/collections/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {ADMIN_TOKEN}" \
-d '{
"fields": {
"sku": {
"type": "String",
"required": true,
"pattern": "^[A-Z0-9-]+$"
},
"name": {
"type": "String",
"required": true,
"max_length": 200
},
"price": {
"type": "Number",
"min": 0.01,
"required": true
},
"category": {
"type": "String",
"enum": ["electronics", "clothing", "books", "food"]
},
"in_stock": {
"type": "Boolean",
"default": true
},
"tags": {
"type": "Array",
"items": {
"type": "String"
},
"max_items": 5
}
}
}'

# 2. Set custom primary key
curl -X PUT https://{EKODB_API_URL}/api/schemas/products/primary-key-alias \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {ADMIN_TOKEN}" \
-d '{
"alias": "sku"
}'

# 3. Insert product (validates against schema)
curl -X POST https://{EKODB_API_URL}/api/insert/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {YOUR_API_TOKEN}" \
-d '{
"sku": "ELEC-001",
"name": "Wireless Mouse",
"price": 29.99,
"category": "electronics",
"in_stock": true,
"tags": ["wireless", "bluetooth", "ergonomic"]
}'

# 4. Get collection info
curl -X GET https://{EKODB_API_URL}/api/collections/products \
-H "Authorization: Bearer {YOUR_API_TOKEN}"

# 5. Get current schema
curl -X GET https://{EKODB_API_URL}/api/schemas/products \
-H "Authorization: Bearer {YOUR_API_TOKEN}"

# 6. Update schema constraints
curl -X PUT https://{EKODB_API_URL}/api/schemas/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {ADMIN_TOKEN}" \
-d '{
"fields": {
"sku": {
"type": "String",
"required": true,
"pattern": "^[A-Z0-9-]+$"
},
"name": {
"type": "String",
"required": true,
"max_length": 300
},
"price": {
"type": "Number",
"min": 0.01,
"max": 100000
}
}
}'

Best Practices

Schema Design

Start Simple, Evolve Gradually:

# Initial schema - minimal constraints
{
"fields": {
"name": {"type": "String", "required": true},
"email": {"type": "String", "required": true}
}
}

# Later - add more constraints as requirements clarify
{
"fields": {
"name": {
"type": "String",
"required": true,
"min_length": 2,
"max_length": 100
},
"email": {
"type": "String",
"required": true
}
}
}

Collection Naming

Use Clear, Plural Names:

# Good
/api/collections/users
/api/collections/products
/api/collections/order_items

# Avoid
/api/collections/user
/api/collections/Product
/api/collections/order-item

Schema Validation

Balance Strictness with Flexibility:

{
"fields": {
"core_field": {
"type": "String",
"required": true,
"max_length": 100
},
"optional_field": {
"type": "String",
"required": false
}
}
}

Primary Key Strategy

Choose Based on Your Use Case:

Use CasePrimary Key Strategy
Auto-generated IDsUse default id field
External system syncSet alias to external ID
Natural keys (SKU, email)Set alias to natural key
UUIDsSet alias to UUID field

Validation Errors

When a record violates the schema, you'll receive detailed error messages:

# Invalid insert attempt
POST /api/insert/users
{
"name": "A", // Too short
"email": "invalid-email", // Invalid format
"age": 200 // Exceeds max
}

# Error response
{
"error": "Schema validation failed",
"details": [
{
"field": "name",
"constraint": "min_length",
"expected": 2,
"actual": 1,
"message": "Field 'name' must be at least 2 characters"
},
{
"field": "email",
"constraint": "pattern",
"message": "Field 'email' does not match required pattern"
},
{
"field": "age",
"constraint": "max",
"expected": 150,
"actual": 200,
"message": "Field 'age' exceeds maximum value of 150"
}
]
}

Example Code

Direct HTTP/REST API Examples

Raw HTTP examples demonstrating the REST API directly:

  • JavaScript: collection_management.js
  • Python: collection_management.py
  • Go: collection_management.go
  • Rust: collection_management.rs

Client Library Examples

Production-ready examples using official client libraries:

  • Rust: client_collection_management.rs
  • Python: client_collection_management.py
  • TypeScript: client_collection_management.ts
  • Go: client_collection_management.go
  • Kotlin: ClientCollectionManagement.kt
  • JavaScript: client_collection_management.js