如何在Mongoose Schema中定义动态对象属性的ObjectId类型?
问题描述
当前使用的Mongoose Schema定义如下:
const schema = new mongoose.Schema({ filters: { type: Object, default: {} } });
示例输入文档:
{ filters: { field1: "5a934e000102030405000001", field2: "5a934e000102030405000002", field3: "5a934e000102030405000003" } }
其中filters是存储动态属性的对象,所有属性值均为ObjectId类型。目前通过pre-save钩子配合lodash实现属性值到ObjectId的转换:
SchemaObj.pre('save', function (next) { this.filters = _.reduce(this.filters, (r, v, k) => v ? { ...r, [k]: mongoose.Types.ObjectId(v) } : r, {}); next(); });
想了解是否存在更直接的方式,能在Schema定义阶段就指定动态对象属性的类型为ObjectId,比如类似以下期望的写法:
const schema = new mongoose.Schema({ filters: { type: { *: mongoose.Types.ObjectId } } });
可行方案
1. 使用Mongoose Map类型
Mongoose原生支持Map类型,可直接指定键值对中值的类型,完美适配动态属性场景:
const schema = new mongoose.Schema({ filters: { type: Map, of: mongoose.Schema.Types.ObjectId, default: {} } });
定义后,Mongoose会自动将filters中的所有值转换为ObjectId类型,无需额外的pre-hook处理。存入字符串形式的ObjectId时会自动转换,读取时返回ObjectId实例。
2. 自定义字段的Setter与验证器
若不想使用Map类型,可给filters字段添加自定义setter自动转换类型,同时配合验证器确保所有值为合法ObjectId:
const schema = new mongoose.Schema({ filters: { type: Object, default: {}, // 自动转换属性值为ObjectId set: function(filters) { if (!filters) return {}; return Object.entries(filters).reduce((acc, [key, val]) => { if (val) acc[key] = mongoose.Types.ObjectId(val); return acc; }, {}); }, // 验证所有属性值均为合法ObjectId validate: { validator: function(filters) { return Object.values(filters).every(val => mongoose.Types.ObjectId.isValid(val)); }, message: props => `filters中存在非法的ObjectId值: ${props.value}` } } });
这种方式在设置filters值时就会自动转换类型,同时做合法性校验,比pre-hook的处理时机更提前。
3. Mixed类型配合字段转换逻辑
若需更灵活的处理,可使用Mongoose的Mixed类型,再通过schema.path()添加转换逻辑:
const schema = new mongoose.Schema({ filters: { type: mongoose.Schema.Types.Mixed, default: {} } }); // 给filters字段添加值转换逻辑 schema.path('filters').set(function(filters) { if (!filters) return {}; return Object.fromEntries( Object.entries(filters).map(([k, v]) => [k, v ? mongoose.Types.ObjectId(v) : v]) ); });
这种方式允许在Schema定义完成后单独配置转换逻辑,适合复杂业务场景。
内容的提问来源于stack exchange,提问作者turivishal
相关产品推荐
相关产品推荐

