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
Document instance methods for saving, validation, field access, and lifecycle management with change tracking and middleware support.
Methods for saving, validating, and managing document lifecycle with automatic change detection.
interface Document {
/**
* Save document to database
* @param options - Save options
* @returns Promise resolving to saved document
*/
save(options?: SaveOptions): Promise<this>;
/**
* Validate document against schema
* @param pathsToValidate - Specific paths to validate
* @param options - Validation options
* @returns Promise resolving when validation completes
*/
validate(pathsToValidate?: string[], options?: ValidateOptions): Promise<void>;
/**
* Synchronously validate document
* @param pathsToValidate - Specific paths to validate
* @returns ValidationError if invalid, null if valid
*/
validateSync(pathsToValidate?: string[]): ValidationError | null;
/**
* Delete this document
* @param options - Delete options
* @returns Promise resolving to deleted document
*/
deleteOne(options?: DeleteOptions): Promise<this>;
/**
* Remove document (deprecated, use deleteOne)
* @param options - Remove options
* @returns Promise resolving to removed document
*/
remove(options?: RemoveOptions): Promise<this>;
}
interface SaveOptions {
/** Skip validation */
validateBeforeSave?: boolean;
/** Validate only modified paths */
validateModifiedOnly?: boolean;
/** Specific paths to validate */
pathsToValidate?: string[];
/** Database session */
session?: ClientSession;
/** Suppress '_id' on save */
suppressReservedKeysWarning?: boolean;
}Usage Examples:
const User = mongoose.model('User', userSchema);
// Create and save document
const user = new User({
name: 'John Doe',
email: 'john@example.com',
age: 30
});
await user.save();
// Validate before operations
try {
await user.validate();
console.log('Document is valid');
} catch (error) {
console.log('Validation errors:', error.errors);
}
// Save with options
await user.save({
validateBeforeSave: false,
pathsToValidate: ['name', 'email']
});
// Delete document
await user.deleteOne();Methods for getting, setting, and tracking changes to document fields.
interface Document {
/**
* Get field value with path notation
* @param path - Field path (dot notation supported)
* @param type - Cast to specific type
* @returns Field value
*/
get(path: string, type?: any): any;
/**
* Set field value with path notation
* @param path - Field path or object of paths/values
* @param val - Value to set
* @param type - Schema type for casting
* @param options - Set options
* @returns this document
*/
set(path: string | object, val?: any, type?: any, options?: SetOptions): this;
/**
* Mark field as modified for change tracking
* @param path - Field path to mark as modified
* @param val - New value (optional)
* @returns this document
*/
markModified(path: string, val?: any): this;
/**
* Unmark field as modified
* @param path - Field path to unmark
* @returns this document
*/
unmarkModified(path: string): this;
/**
* Check if field is modified
* @param path - Field path to check (optional, checks any modification if omitted)
* @returns true if modified
*/
isModified(path?: string): boolean;
/**
* Get array of modified field paths
* @param options - Options for getting modified paths
* @returns Array of modified paths
*/
modifiedPaths(options?: { includeChildren?: boolean }): string[];
/**
* Check if field was selected in query
* @param path - Field path to check
* @returns true if selected
*/
isSelected(path: string): boolean;
/**
* Check if field is initialized
* @param path - Field path to check
* @returns true if initialized
*/
isInit(path: string): boolean;
}
interface SetOptions {
/** Strict mode for this operation */
strict?: boolean;
/** Merge objects instead of overwriting */
merge?: boolean;
}Usage Examples:
const user = new User({ name: 'John', profile: { age: 30 } });
// Get field values
console.log(user.get('name')); // 'John'
console.log(user.get('profile.age')); // 30
// Set field values
user.set('name', 'Jane');
user.set('profile.age', 31);
// Set multiple fields at once
user.set({
name: 'Bob',
email: 'bob@example.com'
});
// Check modifications
console.log(user.isModified('name')); // true
console.log(user.modifiedPaths()); // ['name', 'profile.age']
// Mark additional fields as modified
user.markModified('customField');
// Reset modification tracking
user.unmarkModified('name');Key properties available on all document instances.
interface Document {
/** Document ID as string */
id: string;
/** Document ObjectId */
_id: ObjectId;
/** True if document is new (not saved to database) */
isNew: boolean;
/** Document version number (if versioning enabled) */
__v?: number;
/** Reference to document's schema */
$__: DocumentInternals;
/** Document errors from validation */
errors?: ValidationError;
/** True if document is deleted */
$isDeleted: boolean;
}Convert documents to plain JavaScript objects or JSON with transformation options.
interface Document {
/**
* Convert document to plain JavaScript object
* @param options - Transformation options
* @returns Plain object representation
*/
toObject(options?: ToObjectOptions): any;
/**
* Convert document to JSON representation
* @param options - Transformation options
* @returns JSON-serializable object
*/
toJSON(options?: ToObjectOptions): any;
/**
* Get string representation of document
* @returns String representation
*/
toString(): string;
/**
* Inspect document (Node.js util.inspect)
* @returns Object for inspection
*/
inspect(): any;
}
interface ToObjectOptions {
/** Include getter functions */
getters?: boolean;
/** Include virtual properties */
virtuals?: boolean;
/** Include version key */
versionKey?: boolean;
/** Minimize empty objects */
minimize?: boolean;
/** Transform function */
transform?: (doc: any, ret: any, options: any) => any;
/** Flatten Maps to objects */
flattenMaps?: boolean;
/** Depopulate populated paths */
depopulate?: boolean;
/** Use aliases instead of actual field names */
useProjection?: boolean;
}Usage Examples:
const user = await User.findById(userId).populate('friends');
// Convert to plain object
const userObj = user.toObject();
// Convert with options
const cleanUser = user.toObject({
virtuals: true,
getters: true,
minimize: false,
transform: function(doc, ret) {
delete ret._id;
delete ret.__v;
return ret;
}
});
// Convert to JSON (used by JSON.stringify)
const userJson = user.toJSON();
// Custom JSON transformation
userSchema.set('toJSON', {
virtuals: true,
transform: function(doc, ret) {
ret.id = ret._id;
delete ret._id;
delete ret.__v;
return ret;
}
});Populate referenced documents and manage populated data.
interface Document {
/**
* Populate referenced fields
* @param path - Path to populate or populate options
* @returns Promise resolving to populated document
*/
populate(path: string | PopulateOptions | PopulateOptions[]): Promise<this>;
/**
* Get populated document(s) for a path
* @param path - Path to check
* @returns Populated value or undefined
*/
populated(path: string): any;
/**
* Remove populated values and restore ObjectIds
* @param path - Path to depopulate (optional, depopulates all if omitted)
* @returns this document
*/
depopulate(path?: string): this;
/**
* Explicitly populate virtual fields
* @param path - Virtual path to populate
* @returns Promise resolving to populated document
*/
execPopulate(): Promise<this>;
}
interface PopulateOptions {
/** Path to populate */
path: string;
/** Fields to select from populated documents */
select?: string | object;
/** Model to populate from */
model?: string | Model<any>;
/** Additional query conditions */
match?: any;
/** Sort populated documents */
sort?: any;
/** Limit populated documents */
limit?: number;
/** Skip populated documents */
skip?: number;
/** Populate nested fields */
populate?: PopulateOptions | PopulateOptions[];
/** Preserve null and undefined values */
strictPopulate?: boolean;
}Usage Examples:
// Schema with references
const postSchema = new Schema({
title: String,
author: { type: Schema.Types.ObjectId, ref: 'User' },
comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }]
});
const post = await Post.findById(postId);
// Basic population
await post.populate('author');
console.log(post.author.name); // Populated user name
// Population with field selection
await post.populate('author', 'name email');
// Population with conditions
await post.populate({
path: 'comments',
match: { approved: true },
select: 'text createdAt',
sort: { createdAt: -1 }
});
// Multiple populations
await post.populate([
{ path: 'author', select: 'name' },
{ path: 'comments', populate: { path: 'author', select: 'name' } }
]);
// Check if populated
if (post.populated('author')) {
console.log('Author is populated');
}
// Depopulate
post.depopulate('author');
console.log(post.author); // ObjectId againMethods for comparing documents and performing advanced manipulations.
interface Document {
/**
* Check equality with another document
* @param doc - Document to compare with
* @returns true if equal
*/
equals(doc: Document): boolean;
/**
* Increment numeric field values
* @returns this document
*/
increment(): this;
/**
* Overwrite document with new data
* @param obj - New document data
* @returns this document
*/
overwrite(obj: any): this;
/**
* Update document in database
* @param update - Update operations
* @param options - Update options
* @returns Query instance
*/
updateOne(update: UpdateQuery<this>, options?: UpdateOptions): Query<UpdateResult, this>;
/**
* Replace document in database
* @param replacement - Replacement data
* @param options - Replace options
* @returns Query instance
*/
replaceOne(replacement: any, options?: ReplaceOptions): Query<UpdateResult, this>;
}Usage Examples:
const user1 = await User.findById(id1);
const user2 = await User.findById(id2);
// Compare documents
if (user1.equals(user2)) {
console.log('Same document');
}
// Increment version
user1.increment();
await user1.save();
// Overwrite with new data
user1.overwrite({
name: 'New Name',
email: 'new@example.com'
});
// Update in database
await user1.updateOne({ $set: { lastLogin: new Date() } });
// Replace in database
await user1.replaceOne({
name: 'Replacement Name',
email: 'replacement@example.com'
});interface ValidateOptions {
/** Paths to skip during validation */
pathsToSkip?: string[];
/** Run validators on all paths */
validateModifiedOnly?: boolean;
}
interface ValidationError extends Error {
/** Validation errors by path */
errors: { [path: string]: ValidatorError };
/** Error type identifier */
kind: 'ValidationError';
}
interface ValidatorError extends Error {
/** Path that failed validation */
path: string;
/** Value that failed validation */
value: any;
/** Validator type */
kind: string;
/** Schema type that failed */
schemaType: SchemaType;
}
interface DocumentInternals {
/** Document state tracking */
selected: any;
modified: Set<string>;
errors: ValidationError;
validationError: ValidationError;
adhocPaths: any;
removing: boolean;
inserting: boolean;
version: number;
getters: any;
populate: any;
populated: any;
wasPopulated: boolean;
scope: any;
activePaths: any;
pathsToScopes: any;
cachedRequired: any;
session: ClientSession;
ownerDocument: Document;
fullPath: string;
emitter: EventEmitter;
'$options': any;
}