Mongoose如何根据国家属性值动态设置对应城市的枚举选项?
Mongoose 国家-城市联动枚举实现方案
因为Mongoose Schema的enum配置是静态定义的,无法直接读取同文档其他字段的动态值实现联动,你可以通过自定义验证器实现城市枚举随国家动态校验,具体实现如下:
const mongoose = require('mongoose'); // 抽离公共常量,避免重复编码 const COUNTRY_ENUM = ['USA', 'GB', 'CA', 'BR']; const CITIES_MAP = { USA: ['New York', 'Los Angeles', 'Chicago'], GB: ['London', 'Manchester', 'Birmingham'], CA: ['Toronto', 'Vancouver', 'Montreal'], BR: ['São Paulo', 'Rio de Janeiro', 'Brasília'] }; const questionSchema = new mongoose.Schema({ address: { country: { type: String, required: true, enum: COUNTRY_ENUM }, city: { type: String, required: true, // 用自定义验证器实现动态枚举校验 validate: { validator: function(cityVal) { // 此处不能用箭头函数,否则this无法指向当前文档实例 const allowedCities = CITIES_MAP[this.address.country]; // 校验当前填写的城市是否属于对应国家的城市列表 return allowedCities?.includes(cityVal) ?? false; }, // 校验失败的提示信息 message: props => `${props.value} 不属于所选国家的合法城市列表` } } } }); const Question = mongoose.model('Question', questionSchema);
注意事项
- 验证器必须使用普通函数声明,不能用箭头函数,否则会丢失当前文档实例的
this指向,无法读取已填写的country值 - 如果你使用
findOneAndUpdate、updateMany这类更新操作,需要手动开启验证器才能触发城市校验,示例写法:Question.findOneAndUpdate( { _id: 文档ID }, { 'address.city': 'London' }, // 开启运行验证器,否则自定义校验不会生效 { runValidators: true, new: true } ) - 如果国家为非必填字段,可以在验证器中增加
this.address.country的非空判断,适配国家未填写时的校验逻辑
内容的提问来源于stack exchange,提问作者sdob
相关产品推荐
相关产品推荐

