Skip to content

Collections ​

A collection is a group of documents with a name. Collections are created lazily when you first request them.

Installation ​

Add PocketDB to your Cargo.toml:

toml
[dependencies]
pocketdb = "0.1"

Or via the command line:

bash
cargo add pocketdb

Getting a Collection ​

rust
use pocketdb::Database;

let db = Database::open("data.pdb")?;

// Get or create a collection
let users = db.collection("users")?;

// Collections are automatically created when first accessed
let orders = db.collection("orders")?;

Inserting Documents ​

Single Insert ​

rust
use pocketdb::doc;

let id = users.insert(doc! {
    "name" => "Alice",
    "age" => 30,
    "email" => "alice@example.com"
})?;

println!("Inserted with ID: {}", id);

Bulk Insert ​

rust
use pocketdb::doc;

let docs = vec![
    doc! { "name" => "Alice", "age" => 30 },
    doc! { "name" => "Bob", "age" => 25 },
    doc! { "name" => "Charlie", "age" => 35 },
];

let ids = users.insert_many(docs)?;
println!("Inserted {} documents", ids.len());

Querying Documents ​

Find One ​

rust
use pocketdb::{filter, PocketValue};

let user = users.find_one(&filter! { "name" => == "Alice" });

match user {
    Some(doc) => println!("Found: {}", doc),
    None => println!("Not found"),
}

Find All Matching ​

rust
use pocketdb::filter;

let results = users.find(&filter! { "age" => > 25 });

for doc in &results {
    println!("{}", doc);
}

Query Builder (Sort + Skip + Limit) ​

rust
use pocketdb::{filter, PocketValue};
use pocketdb::query::SortDirection;

let results = users.query(&filter! { "age" => > 18 })
    .sort("age", SortDirection::Asc)
    .skip(10)
    .limit(20)
    .exec();

Count Documents ​

rust
use pocketdb::filter;

let count = users.count(&filter! { "age" => > 25 })?;
println!("Users over 25: {}", count);

Distinct Values ​

rust
use pocketdb::filter;

let cities = users.distinct("city", &filter::always_true())?;
for city in &cities {
    println!("City: {}", city);
}

Updating Documents ​

Update One ​

rust
use pocketdb::{filter, PocketValue};
use pocketdb::query::UpdateExpression;

let updated = users.update_one(
    &filter! { "name" => == "Alice" },
    &UpdateExpression::new().set("age", PocketValue::Int(31)),
)?;

println!("Updated: {}", updated);

Update Many ​

rust
let count = users.update_many(
    &filter! { "active" => == true },
    &UpdateExpression::new().set("verified", PocketValue::Bool(true)),
)?;

println!("Updated {} documents", count);

Update Operators ​

OperatorDescriptionExample
$setSet a field value.set("name", value)
$unsetRemove a field.unset("name")
$incIncrement a numeric field.inc("age", PocketValue::Int(1))
$mulMultiply a numeric field.mul("price", PocketValue::Float(1.1))
$minSet to minimum of current and new.min("score", PocketValue::Int(50))
$maxSet to maximum of current and new.max("score", PocketValue::Int(100))
$pushAppend to array.push("tags", PocketValue::String("new".into()))
$addToSetAdd to array if not present.addToSet("tags", value)
$popRemove first/last array element.pop("tags")
$pullRemove matching array elements.pull("tags", value)
$renameRename a field.rename("old_name", "new_name")

Replacing Documents ​

rust
use pocketdb::{filter, doc};

let replaced = users.replace_one(
    &filter! { "name" => == "Alice" },
    &doc! { "name" => "Alice", "age" => 31, "email" => "alice@new.com" },
)?;

Upsert ​

Update if a match exists, otherwise insert:

rust
use pocketdb::{filter, doc};

let id = users.upsert(
    &filter! { "email" => == "alice@example.com" },
    &doc! { "name" => "Alice", "email" => "alice@example.com", "age" => 30 },
)?;

Deleting Documents ​

Delete One ​

rust
let deleted = users.delete_one(&filter! { "name" => == "Alice" })?;

Delete Many ​

rust
let count = users.delete_many(&filter! { "active" => == false })?;
println!("Deleted {} inactive users", count);

Bulk Write Operations ​

Execute multiple operations atomically:

rust
use pocketdb::collection::BulkOp;
use pocketdb::{filter, doc, PocketValue};
use pocketdb::query::UpdateExpression;

let ops = vec![
    BulkOp::Insert(doc! { "name" => "Dave", "age" => 28 }),
    BulkOp::UpdateOne(
        filter! { "name" => == "Alice" },
        UpdateExpression::new().inc("age", PocketValue::Int(1)),
    ),
    BulkOp::DeleteMany(filter! { "active" => == false }),
    BulkOp::ReplaceOne(
        filter! { "name" => == "Bob" },
        doc! { "name" => "Bob", "age" => 26, "updated" => true },
    ),
];

let affected = users.bulk_write(ops)?;

Indexes ​

rust
use pocketdb::index::IndexSpec;

// Create a B+Tree index on the "email" field
users.create_index(IndexSpec::single("email").unique(true))?;

// Create a hash index
users.create_index(IndexSpec::single("username").hash())?;

// Create a TTL index (expire after 1 hour)
users.create_index(IndexSpec::single("session_token").ttl(3_600_000))?;

// Compound index
users.create_index(IndexSpec::compound(&["country", "city"]))?;

// List indexes
let indexes = users.list_indexes();

// Drop an index
users.drop_index("email_idx")?;

// Rebuild all indexes
users.reindex()?;

See Indexes Guide for more details.

Schema Validation ​

rust
use pocketdb::collection::CollectionSchema;

let mut schema = CollectionSchema::new();
schema.require_field("name", "string");
schema.require_field("age", "int");
users.set_schema(schema);

// Now inserts without "name" or "age" fields will fail

Query Plans ​

Use explain to see which index a query uses:

rust
use pocketdb::{filter, PocketValue};

let plan = users.explain(&filter! { "email" => == "alice@example.com" });
println!("Scan type: {:?}", plan.scan);
println!("Used index: {:?}", plan.index);

TTL Sweep ​

Periodically sweep expired TTL documents:

rust
let purged = users.sweep_ttl()?;
println!("Removed {} expired documents", purged);

Drop All Documents ​

rust
users.drop_documents()?;

Collection Info ​

rust
// Collection name
println!("Name: {}", users.name());

// Document count
println!("Count: {}", users.len());

// Check if empty
if users.is_empty() {
    println!("No documents yet");
}

Listing and Dropping Collections ​

rust
// List all collection names
let names = db.list_collections();
for name in &names {
    println!("Collection: {}", name);
}

// Drop a collection
db.drop_collection("old_collection")?;

Complete Example ​

rust
use pocketdb::{Database, doc, filter, PocketValue};
use pocketdb::query::UpdateExpression;

fn main() -> pocketdb::Result<()> {
    let db = Database::open("collections_example.pdb")?;
    let users = db.collection("users")?;

    // Insert
    users.insert(doc! { "name" => "Alice", "age" => 30, "active" => true })?;
    users.insert(doc! { "name" => "Bob", "age" => 25, "active" => false })?;
    users.insert(doc! { "name" => "Charlie", "age" => 35, "active" => true })?;

    // Query
    let active = users.find(&filter! { "active" => == true });
    println!("Active users: {}", active.len());

    // Update
    users.update_one(
        &filter! { "name" => == "Alice" },
        &UpdateExpression::new().set("age", PocketValue::Int(31)),
    )?;

    // Delete
    users.delete_one(&filter! { "name" => == "Bob" })?;

    // Stats
    println!("Remaining: {}", users.len());

    Ok(())
}

Released under the MIT License. Built by Muhammad Fiaz.