Update Operators
PocketDB provides a rich set of update operators for modifying document fields atomically.
Installation
Add PocketDB to your Cargo.toml:
[dependencies]
pocketdb = "0.1"Or via the command line:
cargo add pocketdbCreating Update Expressions
use pocketdb::query::UpdateExpression;
use pocketdb::PocketValue;
// Single operator
let update = UpdateExpression::new()
.set("name", PocketValue::String("Alice".into()));
// Chained operators
let update = UpdateExpression::new()
.set("name", PocketValue::String("Alice".into()))
.inc("age", PocketValue::Int(1))
.push("tags", PocketValue::String("admin".into()));$set — Set a Field Value
Sets the value of a field. Creates the field if it doesn't exist.
use pocketdb::{filter, PocketValue};
use pocketdb::query::UpdateExpression;
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().set("email", PocketValue::String("alice@new.com".into())),
)?;$unset — Remove a Field
Removes a field from the document.
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().unset("phone"),
)?;$inc — Increment a Numeric Field
Atomically increments a numeric field by the given value. Use negative values to decrement.
// Increment age by 1
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().inc("age", PocketValue::Int(1)),
)?;
// Decrement stock by 5
users.update_one(
&filter! { "name" => == "Widget" },
&UpdateExpression::new().inc("stock", PocketValue::Int(-5)),
)?;
// Increment balance by 100.50
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().inc("balance", PocketValue::Float(100.50)),
)?;$mul — Multiply a Numeric Field
Multiplies the value of a numeric field by the given factor.
// Apply 10% price increase
users.update_one(
&filter! { "category" => == "electronics" },
&UpdateExpression::new().mul("price", PocketValue::Float(1.10)),
)?;$min — Set to Minimum
Sets the field to the minimum of its current value and the given value.
// Only update if new value is smaller
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().min("score", PocketValue::Int(50)),
)?;$max — Set to Maximum
Sets the field to the maximum of its current value and the given value.
// Only update if new value is larger
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().max("score", PocketValue::Int(100)),
)?;$rename — Rename a Field
Rames a field from one name to another.
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().rename("username", "login_name"),
)?;$push — Append to Array
Appends a value to an array field.
// Add a single tag
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().push("tags", PocketValue::String("admin".into())),
)?;$addToSet — Add to Array (No Duplicates)
Appends a value to an array only if it doesn't already exist.
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().add_to_set("tags", PocketValue::String("admin".into())),
)?;
// If "admin" was already in tags, it won't be added again$pop — Remove from Array
Removes the first element from an array.
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().pop("tags"),
)?;$pull — Remove Matching Elements
Removes all elements from an array that match the given value.
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new().pull("tags", PocketValue::String("banned".into())),
)?;Chaining Multiple Operators
All operators can be chained in a single update expression:
use pocketdb::{filter, PocketValue};
use pocketdb::query::UpdateExpression;
users.update_one(
&filter! { "name" => == "Alice" },
&UpdateExpression::new()
.set("email", PocketValue::String("alice@new.com".into()))
.inc("age", PocketValue::Int(1))
.push("tags", PocketValue::String("verified".into()))
.unset("temporary_field"),
)?;Update One vs Update Many
| Method | Behavior |
|---|---|
update_one | Updates only the first matching document |
update_many | Updates all matching documents |
// Update first matching document
users.update_one(&filter, &update)?;
// Update all matching documents
let count = users.update_many(&filter, &update)?;
println!("Updated {} documents", count);Using the update! Macro
use pocketdb::update;
let update = update! {
"$set" => { "name" => "Bob" },
"$inc" => { "age" => 1 }
};
users.update_one(&filter! { "name" => == "Alice" }, &update)?;Complete Example
use pocketdb::{Database, doc, filter, PocketValue};
use pocketdb::query::UpdateExpression;
fn main() -> pocketdb::Result<()> {
let db = Database::open("updates_example.pdb")?;
let products = db.collection("products")?;
// Insert sample data
products.insert(doc! {
"name" => "Laptop",
"price" => 999,
"stock" => 50,
"tags" => ["electronics", "computer"],
"active" => true
})?;
// Set a field
products.update_one(
&filter! { "name" => == "Laptop" },
&UpdateExpression::new().set("on_sale", PocketValue::Bool(true)),
)?;
// Increment stock
products.update_one(
&filter! { "name" => == "Laptop" },
&UpdateExpression::new().inc("stock", PocketValue::Int(10)),
)?;
// Apply discount
products.update_one(
&filter! { "name" => == "Laptop" },
&UpdateExpression::new().mul("price", PocketValue::Float(0.9)),
)?;
// Add tag
products.update_one(
&filter! { "name" => == "Laptop" },
&UpdateExpression::new().push("tags", PocketValue::String("sale".into())),
)?;
// Chained update
products.update_one(
&filter! { "name" => == "Laptop" },
&UpdateExpression::new()
.set("last_updated", PocketValue::String("2024-01-01".into()))
.inc("version", PocketValue::Int(1)),
)?;
// Verify
let product = products.find_one(&filter! { "name" => == "Laptop" }).unwrap();
println!("Price: {:?}", product.get("price"));
println!("Stock: {:?}", product.get("stock"));
println!("Tags: {:?}", product.get("tags"));
Ok(())
}