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

NestJS使用Mongoose定义数组类型Schema时出现栈溢出错误

问题:NestJS Mongoose Schema 数组类型属性导致栈溢出错误

我用NestJS为MongoDB构建数据Schema时,遇到了栈溢出错误,具体代码和错误信息如下:

相关代码

Cart Schema

import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { ProductInCartDto } from "../dtos/product-in-cart.dto";

@Schema({ collection: 'carts', timestamps: true })
export class Cart {
    @Prop()
    userId: number;

    @Prop()
    products: ProductInCartDto[];

}

export const CartSchema = SchemaFactory.createForClass(Cart);

ProductInCartDto

export class ProductInCartDto {
    storeId: number;
    productList: {[productId: number]: number}[];
}

测试用CartModel

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Cart } from '../domains/schemas/cart.schema';
import { Model } from 'mongoose';

@Injectable()
export class CartModel {
    constructor(@InjectModel(Cart.name) private cartModel: Model<Cart>) {}
    
    async createCart() {
        return await this.cartModel.create({ 
            userId: 1,
            products: [{
                storeId: 1,
                productList: {
                    1: 1,
                    2: 2
                }
            }]
        });
    }
}

错误信息

[Nest] 33570  - 06/24/2024, 9:14:36 PM   ERROR [HttpExceptionFilter] Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
    at MetadataStorage.getExposedProperties (/home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/src/MetadataStorage.ts:115:23)
    at TransformOperationExecutor.getKeys (/home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/src/TransformOperationExecutor.ts:461:54)
    at TransformOperationExecutor.transform (/home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/src/TransformOperationExecutor.ts:150:25)
    at TransformOperationExecutor.transform (/home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/src/TransformOperationExecutor.ts:327:31)
    at TransformOperationExecutor.transform (/home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/src/TransformOperationExecutor.ts:32

注:数据能成功存入MongoDB,但只要Schema包含数组类型属性就会触发该错误,移除数组则报错消失。


错误原因

核心问题是你直接在Mongoose Schema的@Prop()中使用了**DTO类(ProductInCartDto)**作为数组元素类型。NestJS的Mongoose模块结合class-transformer处理Schema元数据时,会尝试递归解析DTO的结构,但DTO只是用于数据传输的普通类,没有被标记为Mongoose可识别的Schema类型,导致TransformOperationExecutor在转换过程中陷入无限递归,最终触发栈溢出。

简单来说:Mongoose需要明确的Schema定义(要么是基础类型,要么是Mongoose子Schema),而DTO不能直接作为Schema的属性类型使用。


解决方案

你需要把ProductInCartDto转换为Mongoose的子Schema,或者在@Prop()中明确指定MongoDB能识别的类型结构。

方案1:定义子Schema类

把ProductInCartDto改成带@Schema()装饰器的子Schema类:

// product-in-cart.schema.ts
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";

@Schema()
export class ProductInCart {
    @Prop({ required: true })
    storeId: number;

    @Prop({ type: Map, of: Number, required: true })
    productList: Map<number, number>;
}

export const ProductInCartSchema = SchemaFactory.createForClass(ProductInCart);

然后修改Cart Schema:

import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { ProductInCart, ProductInCartSchema } from "./product-in-cart.schema";

@Schema({ collection: 'carts', timestamps: true })
export class Cart {
    @Prop({ required: true })
    userId: number;

    @Prop({ type: [ProductInCartSchema], default: [] })
    products: ProductInCart[];
}

export const CartSchema = SchemaFactory.createForClass(Cart);

方案2:直接在@Prop中指定类型结构

如果不想单独定义子Schema类,可以直接在@Prop()中声明数组元素的结构:

@Schema({ collection: 'carts', timestamps: true })
export class Cart {
    @Prop({ required: true })
    userId: number;

    @Prop({ 
        type: [
            {
                storeId: { type: Number, required: true },
                productList: { type: Map, of: Number, required: true }
            }
        ],
        default: []
    })
    products: Array<{ storeId: number; productList: Map<number, number> }>;
}

这两种方案都能让Mongoose正确识别数组元素的结构,避免class-transformer的递归转换错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:49:55