You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Nest.js中如何让Mongoose支持混合模式或多类型单Schema?

在Nest.js中实现Mongoose单集合多类型(仅存一个类结构)的方案

需求说明

你要实现的是单集合存储不同类型的文档,且每个文档仅对应One/Two/Three中的一种结构,这正好对应Mongoose的「鉴别器(Discriminators)」特性——它允许在同一个集合下使用不同Schema,通过一个鉴别字段区分文档类型,每个文档只会包含对应类型的字段。

适配Nest.js代码的实现步骤

1. 改造基础类与装饰器

首先修改SomeThing类,添加鉴别器字段,并配置discriminatorKey(指定用来区分类型的字段名):

import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type SomeThingDocument = SomeThing & Document;

@Schema({ discriminatorKey: 'thingType' }) // 指定鉴别字段名
export class SomeThing {
  // 用enum限制可选类型,确保只能是三个类对应的标识
  @Prop({ required: true, enum: ['one', 'two', 'three'] })
  thingType: string;
}

2. 定义子类(One/Two/Three)

让三个子类继承SomeThing,并为每个字段添加@Prop装饰器(Mongoose需要这个装饰器识别Schema字段):

@Schema()
export class One extends SomeThing {
  @Prop({ required: true })
  name: string;

  @Prop({ required: true })
  type: string;
}

@Schema()
export class Two extends SomeThing {
  @Prop({ required: true })
  height: number; // 注:原代码中"hight"应为笔误,修正为"height"

  @Prop({ required: true })
  depth: number;
}

@Schema()
export class Three extends SomeThing {
  @Prop({ required: true })
  count: number;

  // 用Record<string, any>替代object,类型更严谨
  @Prop({ required: true, type: Object })
  properties: Record<string, any>;
}

3. 创建Schema与鉴别器

先创建基础的SomeThingSchema,再基于它创建三个子类的鉴别器:

// 创建基础Schema
export const SomeThingSchema = SchemaFactory.createForClass(SomeThing);

// 为每个子类创建鉴别器,绑定到基础Schema
export const OneSchema = SomeThingSchema.discriminator('One', SchemaFactory.createForClass(One));
export const TwoSchema = SomeThingSchema.discriminator('Two', SchemaFactory.createForClass(Two));
export const ThreeSchema = SomeThingSchema.discriminator('Three', SchemaFactory.createForClass(Three));

4. 在Nest模块中注册

只需注册基础的SomeThingSchema即可,鉴别器会自动依附于它:

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { SomeThing, SomeThingSchema } from './your-schema-file';

@Module({
  imports: [
    MongooseModule.forFeature([
      { name: SomeThing.name, schema: SomeThingSchema },
    ]),
  ],
})
export class YourModule {}

5. 业务代码中使用

在Service中注入Model,创建不同类型的文档时指定thingType,Mongoose会自动匹配对应的鉴别器:

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { SomeThingDocument, One, Two, Three } from './your-schema-file';

@Injectable()
export class YourService {
  constructor(
    @InjectModel(SomeThing.name)
    private thingModel: Model<SomeThingDocument>,
  ) {}

  // 创建One类型的文档
  async createOne(data: Omit<One, 'thingType' | '_id'>) {
    const doc = new this.thingModel({ ...data, thingType: 'one' });
    return doc.save();
  }

  // 创建Two类型的文档
  async createTwo(data: Omit<Two, 'thingType' | '_id'>) {
    const doc = new this.thingModel({ ...data, thingType: 'two' });
    return doc.save();
  }

  // 创建Three类型的文档
  async createThree(data: Omit<Three, 'thingType' | '_id'>) {
    const doc = new this.thingModel({ ...data, thingType: 'three' });
    return doc.save();
  }
}

效果说明

  • 每个存入集合的文档只会包含对应类型的字段(比如One类型的文档只有name/type/thingType,不会有height等字段)
  • 查询时,Mongoose会自动根据thingType字段返回对应类型的文档实例
  • 完全符合你“每次仅实现三个类中的一个”的需求,这就是Mongoose官方所说的混合模式的适配方案

内容的提问来源于stack exchange,提问作者Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 15:00:53