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.