v3.3.1
Playground
Guides

References and Population

Model an ObjectId reference, validate populated data, and choose how to type populated queries.

References and Population

Use zRef('ModelName', schema) when a field stores an ObjectId for another Mongoose model. The model name must match the name you pass to mongoose.model().

Define and validate a reference

post-reference.ts
import mongoose from 'mongoose';
import {z} from 'zod/v4';
import {toMongooseSchema, zObjectId, zRef} from '@nullix/zod-mongoose';

const AuthorReadSchema = z.object({
  _id: zObjectId(),
  name: z.string(),
});
const PostZodSchema = z.object({
  title: z.string(),
  author: zRef('Author', AuthorReadSchema),
});

const authorId = new mongoose.Types.ObjectId();
PostZodSchema.parse({title: 'Hello', author: authorId});
PostZodSchema.parse({
  title: 'Hello',
  author: {_id: authorId, name: 'Ada'},
});

const PostMongooseSchema = toMongooseSchema(PostZodSchema);
// PostMongooseSchema.path('author') is an ObjectId path with ref: 'Author'.

Both Zod parses return an ObjectId in author. The populated object must match AuthorReadSchema and include a valid _id. zObjectId() also accepts a 24-character hex string on the server.

Validate a populated object

populateZodSchema() makes a new Zod schema that expects the referenced object itself instead of its ID:

populated-validation.ts
import {populateZodSchema} from '@nullix/zod-mongoose';

const PopulatedPostSchema = populateZodSchema(PostZodSchema, ['author']);
PopulatedPostSchema.parse({
  title: 'Hello',
  author: {_id: authorId, name: 'Ada'},
});

For TypeScript query results, use PopulatedSchema with ordinary Mongoose population or Strict Model for fluent tracking across chained .populate() calls. See Specialized Helpers for their signatures.