MongoDB Schema Validation
Tags: mongodb, nosql, schemavalidation
Published: 2018-05-12 11:54:08

---
title: MongoDB Schema Validation
published: true
description: Saiba como validar inserts e updates de documentos utilizando esse recurso super interessante do MongoDB
tags: mongodb, nosql, schema validation
---

E aí pessoal, tudo certo? Hoje aqui em Porto Alegre, depois de mais uma semana treinando em MongoDB uma turma de devs. E como um dos assuntos foi a validação de documentos, compartilho com vocês uma visão desse recurso que vem se tornando cada dia mais importante.

##Porque validar?

Bom, confesso que a primeira vez que tive notícias sobre o schema validation pensei: meu, pra que delegar isso pra um banco que tem como sua principal característica a performance?

Sim, porque quando pensamos em bancos NoSQL o primeiro que nos vem à cabeça é: vou gravar qualquer coisa, que legal! E realmente na maioria dos projetos iniciados com NoSQL é isso que acontece, porém, a medida em que as aplicações vão crescendo e aumentando o volume dos dados e de acesso, um mínimo de organização é requerido. É aí que entra o Schema Validation!

##Validação no MongoDB, isso é novo?

Não. A validação de documentos foi introduzida originalmente na versão 3.2 e evoluiu muito desde então. O que começou timidamente com suporte a alguns poucos operadores, hoje tem um operador exclusivo e bastante robusto!

Agora com a versão 3.6 temos o $jsonSchema que está baseado no draft 4 do [JSON Schema](http://json-schema.org/).

Quando especificada, a validação ocorrerá a cada insert ou update na coleção criada utilizando a opção *validator*, que por sua vez terá as regras ou expressões de validação.

Assim como todas as funções que possam afetar a performance do banco, o schema validation pode ser ligado ou desligado a qualquer momento e tem alguns comportamentos para esses casos.

##Validation Level e Validation Action

Podemos utilizar o schema validation para uma coleção que já exista e contenha documentos utilizando o comando [collMod](https://docs.mongodb.com/v3.2/reference/command/collMod/#dbcmd.collMod), como também podemos especificar no momento da criação de uma nova especificando as regras através do opção *validator* no comando [db.createCollection()](https://docs.mongodb.com/v3.2/reference/method/db.createCollection/#db.createCollection).

O *validationLevel* determina como o MongoDB aplica as regras de validação para documentos existentes durante um update. Já a opção *validationAction* determina se o MongoDB retornará um **erro** e rejeita os documentos que estão violando as regras de validação ou gravará um **warn** com essas violações no log e permitirá esses documentos inválidos.

##Documentos Existentes

Podemos controlar como o MongoDB gerencia os documentos existentes utilizando a opção *validationLevel*.

Por default, o *validationLevel* é **strict** e o MongoDB aplicará as regras de validação em todos os inserts e updates. Setando o *validationLevel* para **moderate** fará com que as regras sejam aplicadas para os inserts e updates e nos documentos existentes que preencham todos os requisitos da validação. Os documentos existentes na coleção e que não atendam essas regras não serão verificados.

##Aplicando uma validação simples

Nesse exemplo vou criar uma coleção chamada clientes onde vou requerer os campos documento, nome e cep. Vejamos como fica:

```javascript
db.createCollection("clientes", {
    validator: {
       $jsonSchema: {
          bsonType: "object",
          required: [ "documento", "nome", "endereco.cep" ],
          properties: {
                "documento":{
                    bsonType: "string",
                    description: "O Documento é um atributo requerido e contém o CPF do cliente",
                    maxLength: 11,
                    minLength: 11,
                },
                "nome":{
                    bsonType: "string",
                    description: "O Nome é um atributo requerido"
                },
                "endereco.cep": {
                    bsonType: "string",
                    description: "O CEP é um atributo requerido",
                    maxLength: 8,
                    minLength: 8
                }
            }
        }
    }
});
```

Vejamos mais detalhadamente cada uma das opções que especifiquei no *validator*:

###$jsonSchema

Esse é o objeto principal para utilizarmos o schema validation e termos acesso a mais recursos. Dentro dele especificamos o tipo *object* para o *bsonType*, em seguida declaramos um *array* que deverá conter os nomes dos atributos requeridos no documento.

###properties

Nesse nível definimos as propriedades da validação para cada atributo, ou melhor, entramos mais a fundo atributo por atributo e vamos além da simples obrigatoriedade do atributo.

Note que para cada atributo colocamos propriedades diferentes, podemos definir o *bsonType*, dar uma descrição e até definir tamanho mínimo e máximo.

Várias *key-words* são permitidas nas propriedades e nos permitem uma gama gigantesca de combinações para as validações. Veja mais detalhes dessas [*key-words* aqui]( https://docs.mongodb.com/manual/reference/operator/query/jsonSchema/#op._S_jsonSchema)

Esses são os atributos mínimos para habilitar a validação em uma coleção.

##Aceitando ou Rejeitando Documentos Inválidos

Como disse quem controla esse processo de "ok" ou "não ok" na validação é o *validationAction*.

Tendo por base o schema definido em nosso exemplo, com o *validationAction* setado para **error**, todos os documentos que não estiverem dentro das regras serão rejeitados e o MongoDB retornará uma mensagem de erro.

Já para a *action* **warn** o documento será aceito (inserido ou atualizado), porém, um registro no log será gerado, vejamos um exemplo:

```javascript
db.clientes.insert( { nome: "Leandro", status: "Atualizado" } )
```

```bash
2017-12-01T12:31:23.738-0500 W STORAGE  [conn1] Document would fail validation collection: testeSchema.clientes doc: { _id: ObjectId('5a2191ebacbbfc2bdc4dcffc'), nome: "Leandro", status: "Atualizado" }
```

##Restrições e Bypass

Não conseguimos especificar uma validação para as coleções dos bancos **admin**, **local**, **config**. Tampouco para as coleções **system.***

Algumas *roles* podem têm permissão para dar um *bypass* no schema validation, são elas: **[dbAdmin](https://docs.mongodb.com/manual/reference/built-in-roles/#dbAdmin)** e **[restore](https://docs.mongodb.com/manual/reference/built-in-roles/#restore)**. Em um ambiente com autenticação habilitada um *bypass* na validação tem que usar a opção **[bypassDocumentValidation](https://docs.mongodb.com/manual/reference/privilege-actions/#bypassDocumentValidation)**, mas um conselho: não fale dessa opção pra muita gente! Rssss

##Conclusão

Bem pessoal, é isso... espero ter ajudado vocês a conhecerem um pouco mais sobre esse recurso que à medida em que nossos dados crescem se faz cada vez mais necessário. Para mais informações acesse a página com a documentação oficial do MongoDB [aqui](https://docs.mongodb.com/manual/core/schema-validation/#behavior)

Até a próxima...

PS: comecei a escrever em Porto Alegre e terminei no Rio de Janeiro! ;)