typegoose-patterns
MX Space project TypeGoose model patterns. Apply when creating data models, defining schemas, or handling MongoDB operations.
Installation
Suivez les instructions du dépôt pour votre agent. Consultez les fichiers et dépendances avant l’installation.
Voir la source ↗GuidesInstructions
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)
Exemples
Consultez les exemples du dépôt source.
Voir la source ↗Historique source
- Date d’indexation
- 2026-03-11
- Mise à jour de l’index
- 2026-03-11
- Branch
- main
Les dates concernent ce répertoire. Consultez le dépôt pour l’historique du code.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!