This analysis examines a sophisticated generic repository pattern for MongoDB integration in NestJS applications, demonstrating industry-standard practices for database abstraction, error mitigation, and type-safe query orchestration. The implementation adheres to SOLID principles while maintaining full compatibility with Mongoose's feature set.
Core Implementation
The complete unmodified repository class provides foundational CRUD operations:
import { ConflictException, Logger, NotFoundException } from "@nestjs/common";
import { ObjectId } from "mongodb";
import {
  Document,
  FilterQuery,
  FlattenMaps,
  Model,
  QueryOptions,
  SaveOptions,
  UpdateQuery,
  UpdateWithAggregationPipeline,
} from "mongoose";
export class GenericRepository<T extends Document> {
  private readonly internalLogger: Logger;
  private readonly internalModel: Model<T>;
  constructor(model: Model<T>, logger?: Logger) {
    this.internalModel = model;
    this.internalLogger = logger || new Logger(this.constructor.name);
  }
  async create(doc: Partial<T>, saveOptions: SaveOptions = {}): Promise<T> {
    try {
      const createdEntity = new this.internalModel(doc);
      const savedResult = await createdEntity.save(saveOptions);
      return savedResult;
    } catch (error) {
      if (error?.name === "MongoServerError" && error?.code === 11000) {
        this.internalLogger.error("Duplicate key error while creating:", error);
        throw new ConflictException("Document already exists with provided inputs");
      }
      throw error;
    }
  }
  async getAll(
    filter: FilterQuery<T> = {},
    options: QueryOptions = {},
  ): Promise<FlattenMaps<T>[]> {
    try {
      if (!options.sort) {
        options.sort = { createdAt: -1 };
      }
      const result = await this.internalModel
        .find(filter, null, options)
        .lean()
        .exec();
      return result;
    } catch (error) {
      this.internalLogger.error("Error finding entities:", error);
      return [];
    }
  }
  async getOneWhere(
    filter: FilterQuery<T>,
    options: QueryOptions = {},
  ): Promise<T | null> {
    try {
      const result = await this.internalModel
        .findOne(filter, null, options)
        .exec();
      return result;
    } catch (error) {
      this.internalLogger.error("Error finding entity by ID:", error);
      return null;
    }
  }
  async getOneById(id: string, options: QueryOptions = {}): Promise<T | null> {
    try {
      const result = await this.internalModel
        .findOne({ _id: id }, null, options)
        .exec();
      return result;
    } catch (error) {
      this.internalLogger.error("Error finding entity by ID:", error);
      return null;
    }
  }
  async updateOneById(
    documentId: string,
    updated: UpdateWithAggregationPipeline | UpdateQuery<T>,
    options: QueryOptions = {},
  ): Promise<T> {
    try {
      const result = await this.internalModel
        .findOneAndUpdate(
          { _id: documentId },
          { ...updated, updatedAt: new Date() },
          { ...options, new: true },
        )
        .exec();
      if (!result) {
        throw new NotFoundException("Document not found with provided ID");
      }
      return result;
    } catch (error) {
      if (error?.name === "MongoServerError" && error?.code === 11000) {
        this.internalLogger.error("Duplicate key error while updating:", error);
        throw new ConflictException("Document already exists with provided inputs");
      }
      this.internalLogger.error("Error updating one entity:", error);
      throw error;
    }
  }
  async removeOneById(id: string): Promise<boolean> {
    try {
      const { acknowledged } = await this.internalModel
        .deleteOne({ _id: id })
        .exec();
      return acknowledged;
    } catch (error) {
      this.internalLogger.error("Error removing entities:", error);
      throw error;
    }
  }
  async count(filter: FilterQuery<T> = {}): Promise<number> {
    try {
      const count = await this.internalModel.countDocuments(filter).exec();
      return count;
    } catch (error) {
      this.internalLogger.error("Error counting documents:", error);
      throw error;
    }
  }
  async validateObjectIds(listOfIds: string[] = []): Promise<boolean> {
    try {
      if (!Array.isArray(listOfIds) || !listOfIds?.length) {
        return false;
      }
      const objectIdStrings = listOfIds.map(String);
      const objectIds = objectIdStrings.map((id) => new ObjectId(id));
      const result = await this.internalModel
        .find({ _id: { $in: objectIds } })
        .select("_id")
        .lean()
        .exec();
      return listOfIds.length === result?.length;
    } catch (error) {
      this.internalLogger.error("Error during validation:", error);
      return false;
    }
  }
}
Structural Analysis
1. Type-Safe Foundation
- Generic <T extends Document>parameter ensures collection-specific typing
- FlattenMaps return type guarantees lean document serialization
2. Error Mitigation Strategy
- Duplicate key detection (MongoServerError code 11000)
- Contextual exception conversion (ConflictException/NotFoundException)
- Fallthrough error propagation for custom handling
3. Query Optimization
- Automatic createdAt sorting in getAll
- Lean query execution for reduced memory footprint
- Selective _id projection in validateObjectIds
Operational Paradigms
- 
Document Lifecycle Management - Atomic create/update/delete operations
- Built-in timestamp management (createdAt/updatedAt)
 
- 
Validation Protocol - Batch ObjectID verification via $in operator
- Type coercion safeguards for ID lists
 
- 
Audit Capabilities - Count method for aggregate analytics
- Full query logging for operational transparency
 
Enterprise Implementation Scenarios
- 
User Management Systems - Conflict detection during user registration
- Secure credential updates via atomic operations
 
- 
Inventory Control Platforms - Bulk product ID validation for order processing
- Optimized catalog browsing with lean queries
 
- 
Financial Transaction Logs - Immutable audit trails through createdAt sorting
- Atomic balance updates with rollback safeguards
 
Architectural Benefits
- 
Cross-Cutting Concerns - Centralized logging infrastructure
- Uniform error handling patterns
 
- 
Database Agnosticism - Abstracted Mongoose implementation details
- Clear separation between business logic and persistence
 
- 
Performance Considerations - Lean document returns minimize payload size
- Batch operations reduce database roundtrips
 
This implementation establishes a robust foundation for enterprise-grade applications, providing:
- Type Integrity: Compile-time validation of document structures
- Operational Safety: Transaction-ready method signatures
- Diagnostic Visibility: Contextual logging throughout data operations
The pattern serves as a blueprint for complex systems requiring maintainable, scalable data access layers while maintaining full compatibility with MongoDB's native capabilities.
 

 
    
Top comments (0)