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 pocketdbGetting 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
| Operator | Description | Example |
|---|---|---|
$set | Set a field value | .set("name", value) |
$unset | Remove a field | .unset("name") |
$inc | Increment a numeric field | .inc("age", PocketValue::Int(1)) |
$mul | Multiply a numeric field | .mul("price", PocketValue::Float(1.1)) |
$min | Set to minimum of current and new | .min("score", PocketValue::Int(50)) |
$max | Set to maximum of current and new | .max("score", PocketValue::Int(100)) |
$push | Append to array | .push("tags", PocketValue::String("new".into())) |
$addToSet | Add to array if not present | .addToSet("tags", value) |
$pop | Remove first/last array element | .pop("tags") |
$pull | Remove matching array elements | .pull("tags", value) |
$rename | Rename 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 failQuery 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(())
}