A set of utility functions and plugins to simplify common mongoose
operations. Designed for TypeScript
and mongoose
projects with strict type safety.
- Type-safe: Built with TypeScript for robust type checking.
- Efficient: Reduces redundant database queries and simplifies data transformations.
- Flexible: Handles both document instances and ObjectIds seamlessly.
- Population Ready: Designed for mongoose documents with populated references.
-
Data Transformation: Provides plugins to convert query results into
Map
orRecord
objects.
mongoose >=8 is required as peer dependency
npm install mongoose-utility-kit
or
yarn add mongoose-utility-kit
These helpers are designed for mongoose projects using TypeScript with proper document typing. For best results:
- Define your hydrated document types using mongoose's
HydratedDocument
:
// user.ts
import { HydratedDocument } from 'mongoose';
export interface IUser {
name: string;
email: string;
}
export interface IUserDocumentOverrides = { /* ... */ }
export interface IUserVirtuals = { /* ... */ }
export type UserHydratedDocument = HydratedDocument<IUser, IUserDocumentOverrides & IUserVirtuals>;
- Use
PopulatedDoc
for population references:
// comment.ts
import { Types, PopulatedDoc } from "mongoose";
import { UserHydratedDocument } from "./user";
export interface IComment {
user: PopulatedDoc<UserHydratedDocument>;
text: string;
}
Handle both populated documents and ObjectIds safely:
import { getPopulatedDocumentId } from "mongoose-utility-kit";
// With ObjectId reference
const comment = await Comment.findById(someId).orFail();
getPopulatedDocumentId(comment.user); // '507f191e810c19729de860ea'
// With populated document
const comment = await Comment.findById(someId)
.populate<{ user: UserHydratedDocument }>("user")
.orFail();
getPopulatedDocumentId(comment.user); // '507f191e810c19729de860ea'
import { findOrReturnInstance } from "mongoose-utility-kit";
// With ObjectId reference
const comment = await Comment.findById(someId).orFail();
findOrReturnInstance(comment.user, UserModel);
// With populated document
const comment = await Comment.findById(someId)
.populate<{ user: UserHydratedDocument }>("user")
.orFail();
findOrReturnInstance(comment.user, UserModel);
import { findOrReturnManyInstances } from "mongoose-utility-kit";
import { UserHydratedDocument } from "./user";
import { Types } from "mongoose";
const inputs: (UserHydratedDocument | Types.ObjectId)[] = [
existingUserDocument,
new Types.ObjectId(),
];
const users = await findOrReturnManyInstances(inputs, UserModel);
These plugins provide helper methods for Mongoose queries to transform the results into Map
or Record
objects (standard JavaScript objects), using the documents' _id
as the key.
-
toMap(): Returns a
Map
where the key is a string representing the_id
of each document and the value is the document itself. -
toRecords(): Returns a
Record
(a standard JavaScript object) where the key is a string representing the_id
of each document and the value is the document itself.
-
Import the plugins:
import { toMap, toRecords } from "mongoose-utility-kit";
-
Register the plugins with your schema:
type MyModelHydratedDocument = HydratedDocument<IMyModel>; type MyModelType = Model< IMyModel, ToMapQueryHelpers<MyModelHydratedDocument> & ToRecordsQueryHelpers<MyModelHydratedDocument>, {}, {}, MyModelHydratedDocument >; const schema = new mongoose.Schema<IMyModel, MyModelType>({ // Define your schema here name: String, value: Number, }); schema.plugin(toMap); schema.plugin(toRecords); const MyModel = mongoose.model<IMyModel, MyModelType>("MyModel", schema);
// Converts the query result to a Map
const myMap = await MyModel.find({}).toMap(); // new Map<string, MyModel>
// Converts the query result to a Record
const myRecords = await MyModel.find({}).toRecords(); // Record<string, MyModel>
function getPopulatedDocumentId<HydratedDocType extends Document>(
populatedDocument: PopulatedDoc<HydratedDocType>
): string;
Handles: Both populated documents and raw ObjectIds
Throws: If no valid ID found (Error('document incorrect')
)
async function findOrReturnInstance<HydratedDocType extends Document>(
docOrId: HydratedDocType | Types.ObjectId,
MongooseModel: Model<any, any, any, any, HydratedDocType>,
err?: Error | (() => Error)
): Promise<HydratedDocType>;
Throws: Default error or custom error if document not found
async function findOrReturnManyInstances<HydratedDocType extends Document>(
docOrIds: (HydratedDocType | Types.ObjectId)[],
MongooseModel: Model<any, any, any, any, HydratedDocType>
): Promise<HydratedDocType[]>;
yarn test
Tests use mongodb-memory-server
for in-memory MongoDB testing.
- mongoose 8.x+
- TypeScript 4.5+
- Node.js 16+
MIT