如何在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
相关产品推荐
相关产品推荐

