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

如何在Node.js的Mongoose中正确定义含customFields的嵌套对象Schema?

问题:Mongoose中正确定义customFields数组避免自动生成ObjectId

我在创建Collection的Mongoose Schema时,需要包含customFields对象数组(前端传入结构见下文),但当前配置的Schema会给customFields里的每个对象自动生成ObjectId,求正确的配置方式。

前端传入的JSON结构

{
    "name": "Ali",
    "topic": "Books",
    "description": "Gonnabe nice collection",
    "owner": "63397103eb71457cdff0c244",
    "customFields": [
        {
            "title": "Title",
            "type": ""
        },
        {
            "title": "Description",
            "type": "textarea"
        },
        {
            "title": "Number",
            "type": "number"
        }
    ]
}

Collection的POST路由代码

collectionRoute.post(
  "/",
  JWTAuthMiddleware,
  adminAndUserOnly,
  async (req, res, next) => {
    try {
      const collection = new CollectionModal(req.body);
      console.log(collection);
      await collection.save();
      const newCollection = await UsersModal.findByIdAndUpdate(
        req.body.owner,
        {
          $push: { collections: { ...collection, owner: req.user._id } },
        },
        { new: true }
      );
      res.status(201).send(newCollection);
    } catch (error) {
      next(error);
    }
  }
);

当前的Collection Schema

import mongoose from "mongoose";
const { Schema, model } = mongoose;

const collectionSchema = new Schema(
  {
    name: { type: String },
    description: { type: String },
    topic: { type: String },
    image: { type: String },
    customFields: [
      {
        fieldNumber: { type: Number },
        fieldMultilineText: { type: String },
        fieldType: { type: String },
        fieldChecked: { type: Boolean },
        fieldDate: { type: Date },
      },
    ],
    owner: { type: Schema.Types.ObjectId, ref: "User" },
    items: [{ type: Schema.Types.ObjectId, require: true, ref: "Item" }],
  },
  { timestamps: true }
);

collectionSchema.index({ "$**": "text" });
export default model("Collection", collectionSchema);

User Schema

const userSchema = new Schema(
  {
    username: { type: String },
    email: { type: String, unique: true },
    password: { type: String },
    role: { type: String, enum: ["user", "admin"], default: "user" },
    status: { type: String, enum: ["active", "blocked"], default: "active" },
    collections: [{ type: Schema.Types.ObjectId, ref: "Collection" }],
  },
  { timestamps: true }
);

问题现象

服务器端接收的req.body中,customFields的每个对象被自动添加了_id字段(ObjectId),但业务中不需要这个自动生成的ID;同时当前Schema的customFields字段名和前端传入的不匹配,导致数据无法正确映射。


解决方案

1. 修正customFields的Schema定义,禁用自动生成_id

Mongoose默认会给嵌套子文档生成_id,只需在子文档配置中添加_id: false即可禁用,同时要将字段名和前端传入的title、type对应:

import mongoose from "mongoose";
const { Schema, model } = mongoose;

const collectionSchema = new Schema(
  {
    name: { type: String },
    description: { type: String },
    topic: { type: String },
    image: { type: String },
    customFields: [
      {
        title: { type: String }, // 匹配前端的title字段
        type: { type: String },  // 匹配前端的type字段
        _id: false               // 禁用自动生成ObjectId
      },
    ],
    owner: { type: Schema.Types.ObjectId, ref: "User" },
    items: [{ type: Schema.Types.ObjectId, required: true, ref: "Item" }], // 修正拼写错误:require → required
  },
  { timestamps: true }
);

collectionSchema.index({ "$**": "text" });
export default model("Collection", collectionSchema);

2. 修复路由中的用户关联逻辑

User Schema的collections字段定义的是ObjectId数组,当前路由中push了整个collection对象,这会导致数据类型不匹配,应该只存入新创建的collection的_id:

const newCollection = await UsersModal.findByIdAndUpdate(
  req.body.owner,
  {
    $push: { collections: collection._id }, // 仅存入ObjectId
  },
  { new: true }
);

可选:动态字段结构的处理(如果需要)

如果customFields的字段结构不确定、需要动态扩展,可以使用Schema.Types.Mixed类型,同时禁用_id:

customFields: [{ type: Schema.Types.Mixed, _id: false }]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:45:31