Syntax · 5 of 6

for / in loops

Iterate over an array — typically a find result. The loop body runs once per element with var bound to the current item.

Basic shape

for item in collection_or_array {
    // body — has access to `item`
}

Iterating a find result

proc deactivate_stale(days) {
    let users = find("users", {last_seen_days: {$gte: days}})
    for u in users {
        update("users", {_id: u._id}, {$set: {active: false}})
    }
    return {deactivated: count("users", {active: false})}
}

Iterating a literal array

proc seed_categories() {
    let cats = ["electronics", "books", "clothing", "food"]
    for c in cats {
        insert("categories", {name: c, created_at: "now"})
    }
    return {seeded: 4}
}

Filter then loop

proc flag_low_stock(threshold) {
    let lows = find("products", {stock: {$lt: threshold}})
    for p in lows {
        update("products", {sku: p.sku}, {$set: {needs_restock: true}})
        insert("reorder_queue", {sku: p.sku, current: p.stock})
    }
    return {flagged: count("reorder_queue")}
}

Conditional inside the loop

proc charge_subscriptions() {
    let due = find("subscriptions", {status: "active", due: true})
    for sub in due {
        let user = find_one("users", {_id: sub.user_id})
        if user.balance >= sub.price {
            update("users", {_id: sub.user_id}, {$inc: {balance: -sub.price}})
            insert("charges", {sub_id: sub._id, amount: sub.price, status: "ok"})
        } else {
            update("subscriptions", {_id: sub._id}, {$set: {status: "past_due"}})
            insert("charges", {sub_id: sub._id, amount: sub.price, status: "failed"})
        }
    }
    return {processed: count("charges")}
}

Nested loops

proc fanout_notifications(group_id, message) {
    let members = find("group_members", {group_id: group_id})
    for m in members {
        let devices = find("devices", {user_id: m.user_id})
        for d in devices {
            insert("notifications", {
                device_id: d._id,
                user_id: m.user_id,
                message: message,
                status: "queued"
            })
        }
    }
    return {ok: true}
}

Aggregating in a loop

Sometimes aggregate is cleaner — but a loop works fine for small result sets.

proc total_owed(account_id) {
    let invoices = find("invoices", {account_id: account_id, status: "open"})
    let sum = 0
    for i in invoices {
        sum = sum + i.amount
    }
    return {account_id: account_id, owed: sum}
}
Performance tip: if your loop touches the same document many times, prefer one update with an array of $inc/$set fields over many small ones. OCC validates a version per document, not per field.
Report Issue