Advanced
Raw collection access
typescript
const collection = db.users.getCollection();
const changeStream = collection.watch();
await collection.bulkWrite([
{ insertOne: { document: { email: "a@test.com" } } },
]);
await collection.distinct("role");Type inference helpers
typescript
import type { InferSchemaType, CreateInput, SchemasToClient } from "mondel";
type User = InferSchemaType<typeof userSchema>;
type Db = SchemasToClient<typeof schemas>;Custom validation / refinements
typescript
import { zodCreateSchema } from "mondel";
import { z } from "zod";
const base = zodCreateSchema(userSchema);
const withPasswordCheck = base
.refine((d) => d.password === d.confirmPassword, {
message: "Passwords don't match",
path: ["confirmPassword"],
});Aggregation patterns
typescript
interface RoleStat {
_id: string;
count: number;
}
const stats = await db.users.aggregate<RoleStat>([
{ $match: { isActive: true } },
{ $group: { _id: "$role", count: { $sum: 1 } } },
]);Compound & partial indexes
typescript
const userSchema = defineSchema("users", {
fields: {
email: s.string().required(),
isActive: s.boolean().default(true),
},
indexes: [
{
fields: { role: 1, createdAt: -1 },
options: { name: "idx_role_created" },
},
{
fields: { email: 1 },
options: {
unique: true,
partialFilterExpression: { isActive: true },
},
},
{
fields: { name: "text", bio: "text" },
options: { weights: { name: 10, bio: 5 }, name: "idx_search" },
},
],
});Push with --drop-indexes only when you intend to remove unmanaged indexes.
Multiple databases
See Client.
findOneAndUpdate & bulkWrite
typescript
await db.users.findOneAndUpdate(
{ email: "a@b.com" },
{ $set: { lastLoginAt: new Date() } },
{ returnDocument: "after", upsert: false }
);
await db.users.bulkWrite(operations, { ordered: false });Soft delete
See Soft delete recipe.
Request-scoped serverless pattern
typescript
export function dbMiddleware() {
return async (c: any, next: () => Promise<void>) => {
const db = await connect(c.env.MONGODB_URI);
c.set("db", db);
try {
await next();
} finally {
await db.close();
}
};
}Performance tips
- Project fields with
selectwhen documents are large (runtime only). - Paginate with
skip/limitor range queries on indexed fields. - Prefer
createManyover loops ofcreate. - Keep
validation: "strict"in prod unless profiling proves otherwise (validators are cached). - Run
explainviagetCollection()to verifyIXSCAN. - Do not sync indexes on the request path.
Operator validation matrix
| Operator / shape | Validated |
|---|---|
Plain { field: value } | Yes |
$set | Yes |
$setOnInsert | Yes |
$inc $mul $min $max | No |
$push $pull $addToSet $pop | No |
$unset $rename $currentDate | No |
| Pipeline updates | No |
Driver options passthrough
Find helpers accept native options (session, timeoutMS, maxTimeMS, …).
Mondel-specific keys stripped before the driver: select, timestamps, soft.
