typegoose-patterns | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / development / typegoose-patterns

typegoose-patterns

maintained by mx-space

star 492 account_tree 136 verified_user MIT License
bolt View GitHub

name: typegoose-patterns description: MX Space project TypeGoose model patterns. Apply when creating data models, defining schemas, or handling MongoDB operations. user-invocable: false

TypeGoose Model Patterns

Basic Model

import { modelOptions, prop, Severity, index } from '@typegoose/typegoose'
import { BaseModel } from '~/shared/model/base.model'

export const MY_COLLECTION_NAME = 'my_items'

@modelOptions({
  options: {
    customName: MY_COLLECTION_NAME,
    allowMixed: Severity.ALLOW,
  },
})
export class MyModel extends BaseModel {
  @prop({ required: true })
  name!: string

  @prop()
  description?: string
}

Base Model Inheritance

// BaseModel - Base fields
// Includes: _id, created, updated

// WriteBaseModel - Content models
// Includes: title, text, images, meta, modified
export class PostModel extends WriteBaseModel {
  // Additional fields
}

// BaseCommentIndexModel - Supports comments
// Includes: commentsIndex, allowComment

Field Decorators

Basic Fields

@prop({ required: true })        // Required
name!: string

@prop()                          // Optional
description?: string

@prop({ default: true })         // Default value
isPublished: boolean

@prop({ unique: true })          // Unique constraint
slug!: string

@prop({ trim: true })            // Auto trim
title!: string

Indexes

// Single field index
@prop({ index: true })
slug!: string

// Class-level indexes
@index({ slug: 1 })
@index({ created: -1 })
@index({ title: 'text', text: 'text' })  // Text index
export class MyModel extends BaseModel {}

References

import { Ref } from '@typegoose/typegoose'
import { Category } from '~/modules/category/category.model'

// Reference field
@prop({ ref: () => Category, required: true })
categoryId: Ref<Category>

// Auto-populated virtual field
@prop({
  ref: () => Category,
  foreignField: '_id',
  localField: 'categoryId',
  justOne: true,
  autopopulate: true,
})
public category: Ref<Category>

Nested Objects

// Define subdocument class
class Count {
  @prop({ default: 0 })
  read: number

  @prop({ default: 0 })
  like: number
}

// Usage
@prop({ type: Count, default: { read: 0, like: 0 }, _id: false })
count: Count

Arrays

@prop({ type: () => [String] })
tags?: string[]

@prop({ type: () => [ImageModel] })
images?: ImageModel[]

Plugins

import { plugin } from '@typegoose/typegoose'
import mongoosePaginate from 'mongoose-paginate-v2'
import aggregatePaginate from 'mongoose-aggregate-paginate-v2'
import autoPopulate from 'mongoose-autopopulate'

@plugin(mongoosePaginate)      // Pagination
@plugin(aggregatePaginate)     // Aggregate pagination
@plugin(autoPopulate)          // Auto populate
export class MyModel extends BaseModel {}

Protected Keys

export class MyModel extends BaseModel {
  @prop()
  secret?: string

  // Define fields that should not be directly updated
  static get protectedKeys() {
    return ['secret'].concat(super.protectedKeys)
  }
}

Model Registration

In apps/core/src/processors/database/database.models.ts:

import { MyModel } from '~/modules/my/my.model'

export const databaseModels = [
  // ...
  MyModel,
]

Usage in Services

import { InjectModel } from '~/transformers/model.transformer'
import type { ReturnModelType } from '@typegoose/typegoose'
import type { AggregatePaginateModel } from '~/shared/types/mongoose.types'

@Injectable()
export class MyService {
  constructor(
    @InjectModel(MyModel)
    private readonly model: ReturnModelType<typeof MyModel> &
      AggregatePaginateModel<MyModel>,
  ) {}

  // Query - use lean() to return plain object
  async findById(id: string) {
    return this.model.findById(id).lean()
  }

  // Pagination
  async paginate(page: number, size: number) {
    return this.model.paginate({}, { page, limit: size })
  }

  // Aggregate pagination
  async aggregatePaginate(pipeline: any[], page: number, size: number) {
    const aggregate = this.model.aggregate(pipeline)
    return this.model.aggregatePaginate(aggregate, { page, limit: size })
  }
}

Common Query Patterns

// Conditional query
await this.model.find({ isPublished: true }).lean()

// Sorting
await this.model.find().sort({ created: -1 }).lean()

// Field selection
await this.model.find().select('title slug').lean()

// Population
await this.model.find().populate('category').lean()

// Count
await this.model.countDocuments({ isPublished: true })

// Update
await this.model.findByIdAndUpdate(id, data, { new: true }).lean()

// Delete
await this.model.findByIdAndDelete(id)

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 492
GitHub Forks 136
Created Mar 2026
Last Updated 4个月前
development development cms platforms

Related Skills

ui-ux-pro-max
chevron_right
building-agents
chevron_right
ui-ux-pro-max
chevron_right
prisma-expert
chevron_right
nestjs-expert
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.