Você pode especificar a validação de esquema para uma coleção que armazena dados polimórficos ou documentos com estruturas ou esquemas variáveis.
Para criar validação de esquema para vários esquemas em uma única collection, você pode definir os esquemas em suas regras de validação e garantir que os documentos estejam em conformidade com um dos esquemas da sua collection.
Sobre esta tarefa
Considere uma coleção, accounts
, que armazena dados sobre clientes de um banco e os detalhes de suas contas. A coleção contém documentos customer
e documentos account
.
O código a seguir insere dois documentos customer
na coleção accounts
para armazenar os detalhes dos clientes Andre e Ana, respectivamente. Ele também insere dois documentos account
para representar cada uma de suas contas de economia individuais e um terceiro documento account
para representar sua conta atual compartilhada. Você pode executar o código para este tutorial nashell do MongoDB (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 somente documentos que sigam os esquemas customer
ou account
na coleção accounts
, configure a validação de esquema usando o procedimento a seguir.
Passos
Criar uma definição de JSON schema para cada tipo de documento
Para distinguir entre diferentes tipos de documentos, você pode utilizar vários JSON schemas. Para definir quais atributos devem estar em um documento e quais tipos de dados eles aceitam, crie dois esquemas: um para um documento do customer
e outro para um documento do account
. Cada esquema inclui um atributo docType
para identificar qual tipo de entidade ele 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 a collection para aceitar somente os documentos apropriados
Para permitir documentos que correspondam a customerSchema
ou a accountSchema
, use o operador de JSON schema oneOf
. Em seguida, use o comando collMod
para atualizar a collection accounts
a ser usada para sua validação de esquema.
db.runCommand({ collMod: "accounts", validator: { $jsonSchema: { oneOf: [ customerSchema, accountSchema ] } } })
Adicionar validações semânticas extras
Opcionalmente, você pode adicionar validações semânticas extras. Por exemplo, você pode adicionar as seguintes restrições aos documentos da sua collection:
Para documentos
customer
, o valorcustomerSince
não pode ser anterior ao horário atual.Para documentos
account
, o valordateOpened
não pode ser anterior ao horário atual.Para contas de economia, o
balance
não pode cair abaixo de zero.
Você pode implementar as validações extras identificando documentos customer
e account
inválidos e implementando essas restrições na validação de 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 })
Verificar os documentos em sua coleção
Para verificar se todos os documentos que já estão na sua coleção estão de acordo com a nova validação de esquema, use o comando db.collection.validate()
.
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
na saída indica que todos os documentos na collection accounts
estão em conformidade com os esquemas da collection.
Teste a validação de esquema
Para verificar a validação de esquema, você pode tentar inserir um documento inválido na coleção accounts
. Por exemplo, tente inserir um documento customer
sem o campo last
obrigatório, para sobrenome:
db.accounts.insertOne( { "docType": "customer", "customerId": "12345", "name": { "first": "John", }, "customerSince": "2025-01-01T00:00:00Z" } )
MongoServerError: Document failed validation