Skip to content

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

  1. Project fields with select when documents are large (runtime only).
  2. Paginate with skip/limit or range queries on indexed fields.
  3. Prefer createMany over loops of create.
  4. Keep validation: "strict" in prod unless profiling proves otherwise (validators are cached).
  5. Run explain via getCollection() to verify IXSCAN.
  6. Do not sync indexes on the request path.

Operator validation matrix

Operator / shapeValidated
Plain { field: value }Yes
$setYes
$setOnInsertYes
$inc $mul $min $maxNo
$push $pull $addToSet $popNo
$unset $rename $currentDateNo
Pipeline updatesNo

Driver options passthrough

Find helpers accept native options (session, timeoutMS, maxTimeMS, …).
Mondel-specific keys stripped before the driver: select, timestamps, soft.

Released under the MIT License. · llms.txt