Queries
The Mondel query builder is designed to mirror the native MongoDB API, but with significantly enhanced type safety.
CRUD Operations
The client returned from createClient (or factory connect) provides fully typed access to your collections.
const db = await connect(process.env.MONGO_URI);Create
// type-safe: TypeScript validates field types
await db.users.create({
email: "john@example.com",
role: "USER",
});
// bulk creation
await db.users.createMany([{ email: "a@test.com" }, { email: "b@test.com" }]);Read
Mondel supports MongoDB queries directly, leveraging its types for autocomplete.
// Find many matching criteria
const users = await db.users.findMany({
role: "ADMIN",
});
// Find one document
const user = await db.users.findOne({
email: "john@example.com",
});
// Find by ID directly (helper)
const user = await db.users.findById("65a0c...id_string");Update
Updates are also typed, preventing invalid $set operations.
// Update one
await db.users.updateOne({ email: "john@example.com" }, { $set: { role: "ADMIN" } });
// Update many / native options (e.g., upsert)
await db.users.updateMany({ role: "GUEST" }, { $set: { active: false } }, { upsert: false });
// Update by ID directly
await db.users.updateById("65a0c...id_string", { $set: { name: "Updated Name" } });Automatic Timestamps
Mondel automatically manages createdAt and updatedAt timestamps for you, even when using MongoDB operators like $set or $inc.
- On Update:
updatedAtis automatically set to the current date. - On Upsert: If a new document is created,
createdAtis also set.
// updatedAt is automatically added to the $set operation
await db.users.updateOne({ _id: userId }, { $inc: { loginCount: 1 } });
// upsert: true
// If creates: sets createdAt AND updatedAt
// If updates: sets updatedAt
await db.users.updateOne(
{ email: "new@user.com" },
{ $set: { name: "New User" } },
{ upsert: true }
);Delete
await db.users.deleteOne({ email: "bad@user.com" });
await db.users.deleteOne({ email: "bad@user.com" });
await db.users.deleteMany({}); // clear collection
await db.users.deleteById(userId); // convenience helper
## Utilities
Mondel provides helpers for common operations like counting and existence checks.
```typescript
// Count matching documents
const count = await db.users.count({ role: "ADMIN" });
// Check existence (optimized with limit: 1)
const exists = await db.users.exists({ email: "john@example.com" });
if (exists) {
// ...
}Aggregation
For complex data processing, you can drop down to the aggregation framework.
const stats = await db.users.aggregate([
{ $match: { isActive: true } },
{ $group: { _id: "$role", count: { $sum: 1 } } },
]);Selection & Projection
One of the most powerful features of Mondel is type-safe projection. By default, Mondel returns the full document type. However, if you only select specific fields, the return type is narrowed automatically.
const result = await db.users.findOne(
{ email: "john@example.com" },
{ select: { email: true, role: true } } // explicit projection
);
// TypeScript knows result only has email & role
console.log(result.email); // ok
console.log(result.name); // Error: property 'name' does not exist on type '{ email: string; role: ... }'This prevents common bugs where you over-fetch data or try to access fields you excluded from the query.
Native Options
Because Mondel is a thin wrapper, you have full access to MongoDB native features like sessions and collation.
const session = client.startSession();
try {
await session.withTransaction(async () => {
await db.users.create(
{ email: "new@user.com" },
{ session } // pass session to options
);
});
} finally {
await session.endSession();
}