Mongoose is a comprehensive MongoDB object modeling tool designed for asynchronous environments with schema-based validation, query building, and business logic hooks.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Define document structure, validation rules, indexes, virtual properties, and middleware with a rich schema type system for MongoDB collections.
Create schema definitions with type specifications, validation rules, and configuration options.
/**
* Creates a new Schema
* @param definition - Schema field definitions
* @param options - Schema configuration options
*/
class Schema<T = any> {
constructor(definition?: SchemaDefinition<T>, options?: SchemaOptions);
}
// Create schemas with field definitions
const userSchema = new Schema({
name: { type: String, required: true },
email: { type: String, unique: true },
age: { type: Number, min: 0, max: 120 },
tags: [String],
profile: {
bio: String,
website: { type: String, match: /^https?:\/\// }
}
});Methods for modifying and configuring schemas after creation.
interface Schema<T> {
/**
* Add fields to the schema
* @param obj - Field definitions to add
* @param prefix - Path prefix for nested fields
* @returns this schema
*/
add(obj: SchemaDefinition<T>, prefix?: string): this;
/**
* Get or set a schema path
* @param path - Path name
* @param schemaType - SchemaType to set (optional)
* @returns SchemaType or this schema
*/
path(path: string): SchemaType | undefined;
path(path: string, schemaType: SchemaType): this;
/**
* Create a virtual property
* @param name - Virtual property name
* @param options - Virtual options
* @returns VirtualType instance
*/
virtual(name: string, options?: any): VirtualType;
/**
* Define an index
* @param fields - Index specification
* @param options - Index options
* @returns this schema
*/
index(fields: any, options?: any): this;
/**
* Add pre-middleware hook
* @param method - Method name to hook
* @param fn - Middleware function
* @returns this schema
*/
pre(method: string, fn: Function): this;
pre<T>(method: string, fn: (this: T, next: Function) => void): this;
/**
* Add post-middleware hook
* @param method - Method name to hook
* @param fn - Middleware function
* @returns this schema
*/
post(method: string, fn: Function): this;
post<T>(method: string, fn: (this: T, doc: T, next: Function) => void): this;
/**
* Add instance method to documents
* @param name - Method name
* @param fn - Method function
* @returns this schema
*/
method(name: string, fn: Function): this;
method(methods: { [name: string]: Function }): this;
/**
* Add static method to model
* @param name - Method name
* @param fn - Method function
* @returns this schema
*/
static(name: string, fn: Function): this;
static(methods: { [name: string]: Function }): this;
/**
* Register a plugin
* @param plugin - Plugin function
* @param opts - Plugin options
* @returns this schema
*/
plugin(plugin: Function, opts?: any): this;
/**
* Create a copy of this schema
* @returns Cloned schema
*/
clone(): Schema<T>;
/**
* Get array of schema paths
* @param options - Path iteration options
* @returns Array of path names
*/
paths(options?: any): string[];
/**
* Iterate over schema paths
* @param fn - Function called for each path
* @returns this schema
*/
eachPath(fn: (path: string, schemaType: SchemaType) => void): this;
/**
* Create discriminator schema
* @param name - Discriminator name
* @param schema - Discriminator schema
* @param value - Discriminator value
* @returns Discriminator constructor
*/
discriminator<U>(name: string, schema: Schema<U>, value?: string): Model<U>;
/**
* Create new schema with selected paths only
* @param paths - Array of paths to include
* @param options - Schema options
* @returns New schema with selected paths
*/
pick<T>(paths: string[], options?: SchemaOptions): Schema<T>;
/**
* Create new schema excluding specified paths
* @param paths - Array of paths to exclude
* @param options - Schema options
* @returns New schema without excluded paths
*/
omit<T>(paths: string[], options?: SchemaOptions): Schema<T>;
/**
* Remove all indexes from schema
* @returns this schema
*/
clearIndexes(): this;
/**
* Remove specific index from schema
* @param index - Index specification to remove
* @returns this schema
*/
removeIndex(index: string | any): this;
/**
* Define Atlas search index
* @param description - Search index definition
* @returns this schema
*/
searchIndex(description: SearchIndexDescription): this;
/**
* Convert schema to JSON Schema format
* @param options - Conversion options
* @returns JSON Schema representation
*/
toJSONSchema(options?: { useBsonType?: boolean }): Record<string, any>;
/**
* Add method calls to queue for later execution
* @param name - Method name
* @param args - Method arguments
* @returns this schema
*/
queue(name: string, args: any[]): this;
}
// Schema Properties
interface Schema<T> {
/** Array of child schemas */
childSchemas: { schema: Schema, model: any }[];
/** Object containing discriminators */
discriminators?: { [name: string]: Schema };
/** Original object passed to constructor */
obj: SchemaDefinition<T>;
/** All paths and their types */
paths: { [key: string]: SchemaType };
}Usage Examples:
const mongoose = require('mongoose');
const { Schema } = mongoose;
// Basic schema creation
const blogSchema = new Schema({
title: String,
content: String,
author: { type: Schema.Types.ObjectId, ref: 'User' },
tags: [String],
createdAt: { type: Date, default: Date.now }
});
// Add fields after creation
blogSchema.add({
publishedAt: Date,
views: { type: Number, default: 0 }
});
// Create virtual properties
blogSchema.virtual('url').get(function() {
return `/blog/${this._id}`;
});
// Add instance methods
blogSchema.method('incrementViews', function() {
this.views += 1;
return this.save();
});
// Add static methods
blogSchema.static('findByAuthor', function(authorId) {
return this.find({ author: authorId });
});
// Add middleware
blogSchema.pre('save', function() {
if (this.isModified('content')) {
this.publishedAt = new Date();
}
});Built-in schema types for defining field types with validation and casting.
// Built-in schema types
Schema.Types.String: StringSchemaType;
Schema.Types.Number: NumberSchemaType;
Schema.Types.Date: DateSchemaType;
Schema.Types.Boolean: BooleanSchemaType;
Schema.Types.ObjectId: ObjectIdSchemaType;
Schema.Types.Array: ArraySchemaType;
Schema.Types.Buffer: BufferSchemaType;
Schema.Types.Mixed: MixedSchemaType;
Schema.Types.Decimal128: Decimal128SchemaType;
Schema.Types.Map: MapSchemaType;
Schema.Types.UUID: UUIDSchemaType;
Schema.Types.BigInt: BigIntSchemaType;
Schema.Types.Subdocument: SubdocumentSchemaType;
Schema.Types.Int32: Int32SchemaType;
Schema.Types.Double: DoubleSchemaType;
// SchemaType base methods
interface SchemaType {
/** Set as required field */
required(required?: boolean | Function, message?: string): this;
/** Set default value */
default(val: any): this;
/** Set field selection */
select(val: boolean): this;
/** Validate field value */
validate(validator: Function | RegExp, message?: string): this;
/** Set getter transformation */
get(fn: Function): this;
/** Set setter transformation */
set(fn: Function): this;
/** Create index on field */
index(options?: any): this;
/** Create unique index */
unique(val?: boolean): this;
/** Create sparse index */
sparse(val?: boolean): this;
}String-specific schema type with string validation and transformation methods.
interface StringSchemaType extends SchemaType {
/** Convert to lowercase */
lowercase(val?: boolean): this;
/** Convert to uppercase */
uppercase(val?: boolean): this;
/** Trim whitespace */
trim(val?: boolean): this;
/** Validate against regex pattern */
match(regex: RegExp, message?: string): this;
/** Validate against enumerated values */
enum(values: string[] | { values: string[], message?: string }): this;
/** Minimum string length */
minlength(length: number, message?: string): this;
/** Maximum string length */
maxlength(length: number, message?: string): this;
}Number-specific schema type with numeric validation methods.
interface NumberSchemaType extends SchemaType {
/** Minimum value */
min(value: number, message?: string): this;
/** Maximum value */
max(value: number, message?: string): this;
/** Validate against enumerated values */
enum(values: number[] | { values: number[], message?: string }): this;
}Date-specific schema type with date validation and TTL support.
interface DateSchemaType extends SchemaType {
/** Minimum date */
min(value: Date, message?: string): this;
/** Maximum date */
max(value: Date, message?: string): this;
/** Set TTL expiration */
expires(seconds: number | string): this;
}ObjectId-specific schema type with reference support for population.
interface ObjectIdSchemaType extends SchemaType {
/** Reference to another model */
ref(model: string | Model<any>): this;
/** Reference function for dynamic refs */
refPath(path: string): this;
/** Auto-generate ObjectId */
auto(val?: boolean): this;
}Array schema type for defining arrays of values with element validation.
interface ArraySchemaType extends SchemaType {
/** Validate array of specific type */
of(schemaType: SchemaType): this;
/** Validate array of ObjectIds with reference */
ref(model: string): this;
}
// Array field usage examples
const schema = new Schema({
tags: [String], // Array of strings
scores: [{ type: Number, min: 0, max: 100 }], // Array of numbers with validation
authors: [{ type: Schema.Types.ObjectId, ref: 'User' }], // Array of references
metadata: [Schema.Types.Mixed], // Array of mixed types
comments: [{ // Array of subdocuments
text: String,
author: String,
createdAt: { type: Date, default: Date.now }
}]
});Create computed properties that don't persist to MongoDB but are available on documents.
interface VirtualType {
/** Define getter function */
get(fn: Function): this;
/** Define setter function */
set(fn: Function): this;
/** Set virtual options */
options(opts: any): this;
}Usage Examples:
// Virtual property with getter only
userSchema.virtual('fullName').get(function() {
return `${this.firstName} ${this.lastName}`;
});
// Virtual property with getter and setter
userSchema.virtual('fullName')
.get(function() {
return `${this.firstName} ${this.lastName}`;
})
.set(function(name) {
const parts = name.split(' ');
this.firstName = parts[0];
this.lastName = parts[1];
});
// Virtual populate (for reverse relationships)
userSchema.virtual('posts', {
ref: 'Post',
localField: '_id',
foreignField: 'author'
});Pre and post middleware for intercepting document and model operations.
// Pre middleware - runs before the operation
schema.pre('save', function(next) {
// 'this' refers to the document
this.modifiedAt = new Date();
next();
});
// Pre middleware with async/await
schema.pre('save', async function() {
// Async operations
await this.populate('author');
});
// Post middleware - runs after the operation
schema.post('save', function(doc, next) {
console.log('Document saved:', doc._id);
next();
});
// Post middleware for error handling
schema.post('save', function(error, doc, next) {
if (error.name === 'MongoError' && error.code === 11000) {
next(new Error('Duplicate key error'));
} else {
next(error);
}
});
// Available middleware hooks
'init', 'validate', 'save', 'remove', 'deleteOne', 'deleteMany',
'updateOne', 'updateMany', 'findOneAndDelete', 'findOneAndUpdate',
'insertMany', 'aggregate'interface SchemaOptions {
/** Auto-create indexes */
autoIndex?: boolean;
/** Auto-create collection */
autoCreate?: boolean;
/** Buffer commands when disconnected */
bufferCommands?: boolean;
/** Capped collection options */
capped?: boolean | number | { size?: number; max?: number; };
/** Collection name */
collection?: string;
/** Discriminator key field name */
discriminatorKey?: string;
/** Include virtual 'id' field */
id?: boolean;
/** Include '_id' field */
_id?: boolean;
/** Minimize empty objects */
minimize?: boolean;
/** Read preference */
read?: string;
/** Write concern */
writeConcern?: any;
/** Shard key */
shardKey?: any;
/** Strict mode for schema */
strict?: boolean | 'throw';
/** Strict mode for queries */
strictQuery?: boolean | 'throw';
/** toJSON transform options */
toJSON?: ToObjectOptions;
/** toObject transform options */
toObject?: ToObjectOptions;
/** Type key for discriminators */
typeKey?: string;
/** Validate before save */
validateBeforeSave?: boolean;
/** Version key field name */
versionKey?: string | boolean;
/** Automatic timestamps */
timestamps?: boolean | SchemaTimestampsConfig;
/** Skip version increment */
skipVersioning?: any;
/** Use nested strict mode */
useNestedStrict?: boolean;
}
interface SchemaTimestampsConfig {
/** Created at field name */
createdAt?: boolean | string;
/** Updated at field name */
updatedAt?: boolean | string;
/** Function to get current time */
currentTime?: () => Date;
}
interface ToObjectOptions {
/** Include getters */
getters?: boolean;
/** Include virtuals */
virtuals?: boolean;
/** Minimize empty objects */
minimize?: boolean;
/** Transform function */
transform?: Function;
/** Depopulate populated fields */
depopulate?: boolean;
/** Include version key */
versionKey?: boolean;
/** Return POJO instead of document */
flattenMaps?: boolean;
}
type SchemaDefinition<T> = {
[K in keyof T]?: SchemaTypeOptions<T[K]> | Schema | SchemaType;
};
interface SchemaTypeOptions<T> {
type?: any;
required?: boolean | [boolean, string] | Function;
default?: T | Function;
select?: boolean;
validate?: Function | RegExp | [Function, string] | [RegExp, string];
get?: Function;
set?: Function;
alias?: string;
index?: boolean | any;
unique?: boolean;
sparse?: boolean;
ref?: string | Model<any> | Function;
refPath?: string;
// String-specific options
lowercase?: boolean;
uppercase?: boolean;
trim?: boolean;
match?: RegExp | [RegExp, string];
enum?: T[] | { values: T[], message?: string };
minlength?: number | [number, string];
maxlength?: number | [number, string];
// Number-specific options
min?: number | [number, string];
max?: number | [number, string];
// Date-specific options
expires?: number | string;
// Array-specific options
of?: SchemaTypeOptions<any>;
}
interface SearchIndexDescription {
/** Index name */
name?: string;
/** Index definition */
definition?: any;
/** Index type */
type?: string;
}