Node.js中MongoDB集合$jsonSchema验证失效问题求助
Fixing $jsonSchema Validation Not Working with MongoDB Node.js Driver
Let's break down why your $jsonSchema validation isn't taking effect and fix it step by step:
Key Issues in Your Current Code
- Existing Collection Skipping Validation: When you call
db.createCollection()on an already-existing collection, MongoDB ignores the validator options entirely. This is the most likely reason your validation isn't working—if you ran the code before setting up validation, the collection was created without it, and subsequent runs don't update it. - Uncontrolled Async Flow: Your
doValidationanddoIndexingmethods run asynchronously without waiting for each other to complete. This can lead to race conditions (like trying to create an index before the collection is properly configured) and makes debugging harder. - Schema Target Mismatch: Your test schema targets a
testfield instead of thecodefield you mentioned needing validation.
Step-by-Step Solution
1. Handle Existing Collections with collMod
To apply validation to both new and existing collections, we'll check if the collection exists first. If it does, we use the collMod command to update its validation rules. If not, we create it with the validator.
2. Use async/await for Predictable Async Flow
This ensures we only create indexes after the collection's validation rules are fully set up, and makes the code easier to read and debug.
3. Explicitly Set Validation Enforcement
We'll add validationLevel: "strict" and validationAction: "error" to ensure all write operations are blocked if they don't match the schema.
Modified Working Code
const BaseRepository = require('../../../db/baseRepository'); const getMongoDBClient = require('../../../db/mongodbClient'); class LanguageRepository //extends BaseRepository { constructor() { this.collectionName = 'languages'; this.dbClient = getMongoDBClient(); // Initialize validation and indexing properly this.init(); } async init() { try { const db = await this.dbClient; // Check if the collection already exists const existingCollections = await db.listCollections({ name: this.collectionName }).toArray(); if (existingCollections.length === 0) { // Create new collection with validation rules await this.createCollectionWithValidation(db); } else { // Update validation rules for existing collection await this.updateCollectionValidation(db); } // Create index after collection is properly configured await this.createIndex(db); console.log('Language collection initialized with validation and index successfully'); } catch (err) { console.error('Failed to initialize Language repository:', err); } } async createCollectionWithValidation(db) { await db.createCollection(this.collectionName, { validator: { $jsonSchema: { bsonType: "object", required: ["code"], // Enforce code is always present properties: { code: { bsonType: "string", pattern: "^[a-zA-Z]{2}$", // Enforce 2-letter alphabetic code description: "Must be a 2-letter uppercase/lowercase alphabetic string" }, test: { bsonType: "int", minimum: 2017, maximum: 3017, description: "Must be an integer between 2017 and 3017" } } } }, // Ensure all writes (including updates) follow the schema validationLevel: "strict", // Block invalid writes instead of just warning validationAction: "error" }); } async updateCollectionValidation(db) { await db.command({ collMod: this.collectionName, validator: { $jsonSchema: { bsonType: "object", required: ["code"], properties: { code: { bsonType: "string", pattern: "^[a-zA-Z]{2}$", description: "Must be a 2-letter alphabetic string" }, test: { bsonType: "int", minimum: 2017, maximum: 3017, description: "Must be an integer between 2017 and 3017" } } } }, validationLevel: "strict", validationAction: "error" }); } async createIndex(db) { const keys = { code: 1 }; const options = { sparse: true, unique: true }; await db.collection(this.collectionName).createIndex(keys, options); } async add(item) { const db = await this.dbClient; return db.collection(this.collectionName).insertOne(item); } } module.exports = LanguageRepository;
How to Test It
- If you already have a
languagescollection without validation, run this code—it will update the collection to enforce the schema. - Try inserting an invalid document, like:
You should get an error blocking the insertion, confirming validation is working.const repo = new LanguageRepository(); repo.add({ code: '12', test: 2016 }).catch(err => console.log(err));
内容的提问来源于stack exchange,提问作者Mohammed Al-Hanabi
相关产品推荐
相关产品推荐

