如何创建Mongoose Schema确保产品仅选一个必填子分类?
解决Mongoose Schema中必须且只能选择一个子分类的问题
你当前的Schema里,subCategory下的men、women、kids都是可选字段,所以用户可以不填任何子分类就创建产品,甚至可能同时填多个,不符合「必须且只能选一个子分类」的要求。下面提供两种解决方案:
方案一:将subCategory设为单个字符串字段(推荐)
把subCategory改成单独的字符串,通过自定义验证器确保它属于当前category对应的有效子分类列表,同时设置required: true强制必填。代码如下:
const productSchema = new mongoose.Schema({ category: { type: String, required: true, enum: ["men", "women", "kids"] }, subCategory: { type: String, required: true, validate: { validator: function(v) { // 定义各分类对应的子分类列表 const validSubCategories = { men: ["shirts", "t-shirts", "trousers", "jeans"], women: ["shirts", "t-shirts", "trousers", "jeans"], kids: ["shirts", "t-shirts", "trousers", "jeans"] }; // 验证当前subCategory是否属于对应分类的有效列表 return validSubCategories[this.category].includes(v); }, message: props => `${props.value} 不是 ${this.category} 分类下的有效子分类` } } });
方案优势:
- 结构简洁,MongoDB文档更扁平,查询和维护更方便
- 天然保证「只能选一个子分类」(单个字符串字段)
- 通过验证器确保子分类和主分类匹配,同时强制必填
方案二:保持对象结构并添加自定义验证
如果你坚持要保留原来的subCategory对象结构,可以添加自定义验证器,确保:
- 只有与
category匹配的子分类字段存在 - 该字段有值,其他子分类字段必须不存在
代码示例:
const productSchema = new mongoose.Schema({ category: { type: String, required: true, enum: ["men", "women", "kids"] }, subCategory: { type: Object, required: true, validate: { validator: function(subCat) { // 获取当前主分类对应的子分类字段名 const targetSubField = this.category; // 检查subCategory对象中只有目标字段存在,且该字段有值 const keys = Object.keys(subCat); return keys.length === 1 && keys[0] === targetSubField && subCat[targetSubField]; }, message: "必须且只能填写与主分类匹配的子分类" }, // 定义各子分类的可选值 men: { type: String, enum: ["shirts", "t-shirts", "trousers", "jeans"] }, women: { type: String, enum: ["shirts", "t-shirts", "trousers", "jeans"] }, kids: { type: String, enum: ["shirts", "t-shirts", "trousers", "jeans"] } } });
注意事项:
- 这种方式需要用户提交的
subCategory对象里只有对应主分类的字段,比如主分类是men,则subCategory只能是{ men: "shirts" } - 相比方案一,结构更复杂,查询时需要判断不同字段,不够直观
内容的提问来源于stack exchange,提问作者Talha Jutt
相关产品推荐
相关产品推荐

