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.

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.

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.

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.

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.

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.

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);
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​

Apply a partial update to one or more fields' schema constraints on an existing collection. Only the attributes you set are changed — anything left unset keeps its current value; this does not replace the schema wholesale (see Create Collection above for that).

Admin Permission Required

Updating schema constraints requires admin permissions.

use std::collections::HashMap;

let mut constraints = HashMap::new();
constraints.insert(
"email".to_string(),
SchemaConstraintUpdate {
required: Some(true),
..Default::default()
},
);
constraints.insert(
"age".to_string(),
SchemaConstraintUpdate {
field_type: Some("Integer".to_string()),
min: Some(18.0),
max: Some(100.0),
..Default::default()
},
);

client.update_schema_constraints("users", constraints).await?;
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.

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, None).await?;

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

Schema Field Types​

The key is field_type

Every field definition must carry a field_type key, and it is required — a field definition without it is rejected (missing field 'field_type'). The value is case-sensitive ("String", "Integer", "Vector", …).

Do not confuse this with the type key used in typed value wrappers on records ({ "type": "String", "value": "Alice" }) or in index configs ({ "type": "vector", … }). Those use type; a schema field definition uses field_type.

Supported Data Types​

TypeDescriptionValidation Options
StringText valuesmin, max (length), regex, enums
Integer64-bit signed integersmin, max, enums
Float64-bit floating-point numbersmin, max, enums
NumberIntegers and floatsmin, max, enums
BooleanTrue/false valuesNone
ArrayLists of valuesmin, max (length)
ObjectNested JSON objectsNone
DateTimeRFC 3339 datetime stringsmin, max
DecimalArbitrary-precision decimalsmin, max
UUIDRFC 4122 identifiersNone
VectorNumeric arrays for embeddingsmin, max (length)
SetUnique value collectionsmin, max (length)
BinaryBase64-encoded binary dataNone
BytesRaw byte arraysNone
DurationTime span valuesNone

Field Constraints​

String Constraints:

{
"username": {
"field_type": "String",
"required": true,
"min": 3,
"max": 20,
"regex": "^[a-zA-Z0-9_]+$"
}
}

Number Constraints:

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

Array Constraints:

{
"tags": {
"field_type": "Array",
"min": 1,
"max": 10
}
}

Enum Validation:

{
"status": {
"field_type": "String",
"enums": ["draft", "published", "archived"],
"default": "draft"
}
}

Object Fields:

{
"address": {
"field_type": "Object",
"required": true
}
}

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": {
"field_type": "String",
"required": true,
"regex": "^[A-Z0-9-]+$"
},
"name": {
"field_type": "String",
"required": true,
"max": 200
},
"price": {
"field_type": "Number",
"min": 0.01,
"required": true
},
"category": {
"field_type": "String",
"enums": ["electronics", "clothing", "books", "food"]
},
"in_stock": {
"field_type": "Boolean",
"default": true
},
"tags": {
"field_type": "Array",
"max": 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": {
"field_type": "String",
"required": true,
"regex": "^[A-Z0-9-]+$"
},
"name": {
"field_type": "String",
"required": true,
"max": 300
},
"price": {
"field_type": "Number",
"min": 0.01,
"max": 100000
}
}
}'

Best Practices​

Schema Design​

Start Simple, Evolve Gradually:

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

# Later - add more constraints as requirements clarify
{
"fields": {
"name": {
"field_type": "String",
"required": true,
"min": 2,
"max": 100
},
"email": {
"field_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": {
"field_type": "String",
"required": true,
"max": 100
},
"optional_field": {
"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",
"expected": 2,
"actual": 1,
"message": "Field 'name' must be at least 2 characters"
},
{
"field": "email",
"constraint": "regex",
"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