Puede especificar la validación del esquema para una colección que almacena datos polimórficos o documentos con estructuras o esquemas variables.
Para crear la validación de esquemas para múltiples esquemas dentro de una única colección, puedes configurar los esquemas en tus reglas de validación y asegurarte de que los documentos se ajusten a uno de los esquemas de tu colección.
Acerca de esta tarea
Consideremos una colección, accounts, que almacena datos sobre los clientes de un banco y los detalles de sus cuentas. La colección contiene customer documentos y account documentos.
El siguiente código inserta dos customer documentos en la accounts colección para almacenar los datos de los clientes Andrew y Anne, respectivamente. También inserta dos account documentos para representar cada una de sus cuentas de ahorro individuales y un tercer account documento para representar su cuenta corriente compartida. Puede ejecutar el código de este tutorial en MongoDB Shell (mongosh).
db.accounts.insertMany( [ { "customerId": "CUST-123456789", "docType": "customer", "name": { "title": "Mr", "first": "Andrew", "middle": "James", "last": "Morgan" }, "address": { "street1": "240 Blackfriars Rd", "city": "London", "postCode": "SE1 8NW", "country": "UK" }, "customerSince": ISODate("2005-05-20") }, { "customerId": "CUST-987654321", "docType": "customer", "name": { "title": "Mrs", "first": "Anne", "last": "Morgan" }, "address": { "street1": "240 Blackfriars Rd", "city": "London", "postCode": "SE1 8NW", "country": "UK" }, "customerSince": ISODate("2003-12-01") }, { "accountNumber": "ACC1000000654", "docType": "account", "accountType": "checking", "customerId": [ "CUST-123456789", "CUST-987654321" ], "dateOpened": ISODate("2003-12-01"), "balance": Decimal128("5067.65") }, { "accountNumber": "ACC1000000432", "docType": "account", "accountType": "savings", "customerId": [ "CUST-123456789" ], "dateOpened": ISODate("2005-10-28"), "balance": Decimal128("10341.21") }, { "accountNumber": "ACC1000000890", "docType": "account", "accountType": "savings", "customerId": [ "CUST-987654321" ], "dateOpened": ISODate("2003-12-15"), "balance": Decimal128("10341.89") } ] );
Para permitir únicamente documentos que cumplan con los esquemas customer o account en la colección accounts, configure la validación del esquema utilizando el siguiente procedimiento.
Pasos
Cree una definición de esquema JSON para cada tipo de documento
Para distinguir entre diferentes tipos de documentos, puede usar varios esquemas JSON. Para definir qué atributos deben estar en un documento y qué tipos de datos aceptan, cree dos esquemas: uno para un documento customer y otro para un documento account. Cada esquema incluye un atributo docType para identificar el tipo de entidad que representa.
const customerSchema = { required: ["docType", "customerId", "name", "customerSince"], properties: { docType: { enum: ["customer"] }, customerId: { bsonType: "string"}, name: { bsonType: "object", required: ["first", "last"], properties: { title: { enum: ["Mr", "Mrs", "Ms", "Dr"]}, first: { bsonType: "string" }, middle: { bsonType: "string" }, last: { bsonType: "string" } } }, address: { bsonType: "object", required: ["street1", "city", "postCode", "country"], properties: { street1: { bsonType: "string" }, street2: { bsonType: "string" }, postCode: { bsonType: "string" }, country: { bsonType: "string" } } }, customerSince: { bsonType: "date" } } }; const accountSchema = { required: ["docType", "accountNumber", "accountType", "customerId", "dateOpened", "balance"], properties: { docType: { enum: ["account"] }, accountNumber: { bsonType: "string" }, accountType: { enum: ["checking", "savings", "mortgage", "loan"] }, customerId: { bsonType: "array" }, dateOpened: { bsonType: "date" }, balance: { bsonType: "decimal" } } };
Configurar la colección para aceptar únicamente los documentos adecuados
Para permitir documentos que coincidan con customerSchema o accountSchema, utilice el operador de esquema JSON oneOf. Luego, utilice el collMod Comando para actualizar la accounts colección para usarla en la validación del esquema.
db.runCommand({ collMod: "accounts", validator: { $jsonSchema: { oneOf: [ customerSchema, accountSchema ] } } })
Añadir validaciones semánticas adicionales
Opcionalmente, puede añadir validaciones semánticas adicionales. Por ejemplo, puede añadir las siguientes restricciones a los documentos de su colección:
Para los documentos
customer, el valorcustomerSinceno puede ser anterior a la hora actual.Para los documentos
account, el valordateOpenedno puede ser anterior a la hora actual.Para las cuentas de ahorro, el
balanceno puede caer por debajo de cero.
Puede implementar validaciones adicionales identificando documentos customer y account no válidos e implementando esas restricciones en la validación de su esquema.
const invalidCustomer = { "$expr": { "$gt": ["$customerSince", "$$NOW"] } }; const invalidAccount = { $or: [ { accountType: "savings", balance: { $lt: 0} }, { "$expr": { "$gt": ["$dateOpened", "$$NOW"]} } ] };
const schemaValidation = { "$and": [ { $jsonSchema: { oneOf: [ customerSchema, accountSchema ] }}, { $nor: [ invalidCustomer, invalidAccount ] } ] }; db.runCommand({ collMod: "accounts", validator: schemaValidation })
Verifique los documentos de su colección
Para verificar que todos los documentos que ya están en su colección se adhieren a su nueva validación de esquema, utilice el db.collection.validate() comando.
db.accounts.validate()
{ ns: '66cf8508e64dbb03ce45b30e_test.accounts', uuid: UUID('1aedf62a-f202-4e7c-b434-879057bb6d6b'), nInvalidDocuments: 0, nNonCompliantDocuments: 0, nrecords: 10, nIndexes: 1, keysPerIndex: { _id_: 10 }, indexDetails: { _id_: { valid: true } }, valid: true, repaired: false, readTimestamp: Timestamp({ t: 1749235730, i: 26 }), warnings: [], errors: [], extraIndexEntries: [], missingIndexEntries: [], corruptRecords: [], ok: 1, '$clusterTime': { clusterTime: Timestamp({ t: 1749235753, i: 31 }), signature: { hash: Binary.createFromBase64('3h7qyhLsgU21Pnzf/KVLl8suu2I=', 0), keyId: Long('7449048397505364002') } }, operationTime: Timestamp({ t: 1749235753, i: 31 }) }
nNonCompliantDocuments: 0 en la salida indica que todos los documentos de la colección accounts cumplen con los esquemas de colección.
Pruebe la validación de su esquema
Para verificar la validación de su esquema, puede intentar insertar un documento no válido en la colección accounts. Por ejemplo, intente insertar un documento customer al que le falte el campo last obligatorio para el apellido:
db.accounts.insertOne( { "docType": "customer", "customerId": "12345", "name": { "first": "John", }, "customerSince": "2025-01-01T00:00:00Z" } )
MongoServerError: Document failed validation