如何创建MongoDB严格Schema:带任意字符串键与ObjectID数组值的TS接口
在Nest.js中创建严格匹配动态键值约束的MongoDB Schema
需求概述
需要创建一个MongoDB Schema,满足以下严格约束:
- 文档的键必须是合法字符串(非数字形式的字符串)
- 每个键对应的值必须是MongoDB ObjectID实例的数组
- 拦截所有不符合约束的文档(如单ObjectID值、字符串数组、无效ObjectID、数字键等)
实现方案
利用Mongoose的自定义验证功能结合严格模式,实现对动态键值对的全面校验。以下是完整的TypeScript代码实现:
import { Schema, SchemaTypes, model, Document, ValidatorProps } from 'mongoose'; // 定义TypeScript类型,匹配Schema约束 interface DynamicObjectIDArrayDocument extends Document { [key: string]: Schema.Types.ObjectId[]; } // 创建Schema并添加自定义验证逻辑 const dynamicObjectSchema = new Schema<DynamicObjectIDArrayDocument>({}, { // 严格模式:遇到未知属性直接抛出错误 strict: 'throw', // 自定义文档级验证 validate: { validator: function(doc: DynamicObjectIDArrayDocument) { const docObj = doc.toObject(); // 遍历所有键值对,排除Mongoose内置属性 for (const [key, value] of Object.entries(docObj)) { if (key === '_id' || key === '__v') continue; // 验证键:必须是字符串,且不能是可转换为数字的字符串 if (typeof key !== 'string' || !isNaN(Number(key))) { return false; } // 验证值:必须是数组类型 if (!Array.isArray(value)) { return false; } // 验证数组元素:每个元素必须是有效的ObjectID实例 for (const item of value) { if (!(item instanceof SchemaTypes.ObjectId) || !SchemaTypes.ObjectId.isValid(item.toString())) { return false; } } } return true; }, message: (props: ValidatorProps) => `文档验证失败:${props.path} 的键或值不符合约束` } }); // 创建Nest.js中可注入的模型 export const DynamicObjectModel = model<DynamicObjectIDArrayDocument>('DynamicObject', dynamicObjectSchema);
验证逻辑说明
上述代码会自动拦截所有不合法的文档:
- 拦截单个ObjectID值(如
invalidDocumentProperty_1):验证会检查值是否为数组,非数组直接返回false - 拦截字符串数组(如
invalidDocumentProperty_2):验证数组元素是否为ObjectID实例,字符串无法通过检查 - 拦截无效ObjectID字符串(如
invalidDocumentProperty_3):通过SchemaTypes.ObjectId.isValid()验证字符串是否为合法ObjectID格式 - 拦截数字形式的键(如
invalidDocumentProperty_4):检查键是否为非数字转换的字符串,数字键会被拦截
使用示例
在Nest.js服务中使用该模型时,不符合约束的创建操作会自动抛出验证错误:
// 合法文档:可以成功创建 await DynamicObjectModel.create({ validKey: [SchemaTypes.ObjectId('4edd40c86762e0fb12000003')] }); // 不合法文档:会触发验证错误 await DynamicObjectModel.create({ validKey: SchemaTypes.ObjectId('4edd40c86762e0fb12000003') }).catch(err => { console.error(err.message); // 输出:文档验证失败: 的键或值不符合约束 });
内容的提问来源于stack exchange,提问作者ENcy
相关产品推荐
相关产品推荐

