如何在MongoDB中对包含union-type的AbstractNamespace结构建模并实现校验
MongoDB 多类型Namespace存储Schema实现方案
设计逻辑说明
直接利用MongoDB 3.6及以上版本内置的JSON Schema校验能力,顶层定义所有公共字段约束,通过oneOf关键字实现多子类型的互斥匹配,同时绑定scope枚举值与子类型的对应关系,避免出现字段与类型不匹配的脏数据。
- 集合建议命名为
namespaces,将你定义的全局唯一id字段映射为MongoDB默认主键_id,复用自带的唯一索引,减少冗余存储 - 可自定义
ENUM_SCOPE枚举值为:GLOBAL, CUSTOM, WORKBOOK, WORKSHEET, USER, SOURCE,和6种类型一一对应 - 所有校验规则在集合创建时配置,写入数据时MongoDB会自动触发校验,不符合规则的数据会直接拒绝写入
完整集合创建代码
db.createCollection("namespaces", { validator: { $jsonSchema: { bsonType: "object", // 强制要求所有公共字段必须存在 required: ["_id", "created_at", "scope"], // 公共字段约束 properties: { _id: { bsonType: "string", description: "对应原dataclass的id字段,全局唯一,格式为GLOBAL_SCOPE / CUSTOM_SCOPE::UserID+Name / 类型::ID" }, created_at: { bsonType: "date", description: "创建时间" }, scope: { enum: ["GLOBAL", "CUSTOM", "WORKBOOK", "WORKSHEET", "USER", "SOURCE"], description: "作用域枚举值" } }, // 多类型互斥匹配规则 oneOf: [ // GlobalScope 无独有字段 { properties: { scope: { const: "GLOBAL" } } }, // CustomNamespace { required: ["name", "description", "created_by_id"], properties: { scope: { const: "CUSTOM" }, name: { bsonType: "string" }, description: { bsonType: "string" }, created_by_id: { bsonType: "int" } } }, // WorkbookNamespace { required: ["workbook_id"], properties: { scope: { const: "WORKBOOK" }, workbook_id: { bsonType: "int" } } }, // WorksheetNamespace { required: ["worksheet_id"], properties: { scope: { const: "WORKSHEET" }, worksheet_id: { bsonType: "int" } } }, // UserNamespace { required: ["user_id"], properties: { scope: { const: "USER" }, user_id: { bsonType: "int" } } }, // SourceNamespace { required: ["source_id"], properties: { scope: { const: "SOURCE" }, source_id: { bsonType: "int" } } } ], // 禁止出现所有规则中未定义的额外字段 additionalProperties: false } }, // 校验级别:严格校验所有写入和更新 validationLevel: "strict", validationAction: "error" })
可选配置调整
如果你不想把原id映射为_id,可以将顶层properties中的_id改为id,同时额外给id字段创建唯一索引即可:
// 创建唯一索引 db.namespaces.createIndex({ "id": 1 }, { unique: true })
索引优化建议
给scope字段创建普通索引,提升按作用域类型筛选的查询效率:
db.namespaces.createIndex({ "scope": 1 })
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

