00:00 / 00:00

Fecha publicación: Aug 18, 2021

Schema Validation

Una de las características más potentes que nos ofrece MongoDB es su flexibilidad a la hora de definir esquemas, de hecho hay sitios en donde indican que este es un motor SchemaLess.

Esta ventaja, en algunos casos, se puede convertir en un quebradero de cabeza, ya que hay escenarios en los que sí, es crítico que cierto campo sea obligatorio de informar, o debe tener un tipo dado, incluso queremos que esté en un rango de valores.

Lo chicos de MongoDb a partir de la versión 3.2 nos permiten añadir reglas de validación de esquema a nuestras colecciones.

Manos a la obra

Vamos a crear una base de datos que llamaremos clinica.

use clinica

En esta base de datos queremos crear una colección con los siguientes campos:

  • Nif
  • Nombre
  • Edad
  • Especialidad
  • Diagnostico

Tenemos claro que:

  • El campo nif:
    • Debe estar compuesto por 8 digitos y una letra en Mayuscula.
    • No es obligatorio, ya que algunos pacientes (niños), no lo tienen
  • El campo nombre:
    • Se debe de informar
    • Debe de ser un string.
  • Edad:
    • Se debe informar
    • Debe estar comprendido entre los 0 y los 120 años
  • El campo especialidad debe de:
    • Informarse
    • Ser una de estás entradas: general, pediatria, neurologia
  • El campo diagnostico:
    • Debe de informarse.

Vamos a empezar por crear la colección e indicarles que campos son obligatorios de informar, para ello en el createCollection le indicamos como segundo parametro que vamos a introducir una estructura de validación:

db.createCollection("consultas", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["nombre", "edad", "especialidad", "diagnostico"],
    },
  },
});

Vamos a intentar insertar un documento que no tenga el campo edad

db.consultas.insertOne({
  nombre: "Juan Perez",
  especialidad: "general",
  diagnostico: "Dolor abdominal, Fiebre alta, tos, posible caso de COVID",
});

Cómo podemos ver nos da un error al intentar hacer el insert:

MongoBulkWriteError: Document failed validation

Si ahora informamos el campo edad, podemos ver que funciona correctamente:

db.consultas.insertOne({
  nombre: "Juan Perez",
  edad: 45,
  especialidad: "general",
  diagnostico: "Dolor abdominal, Fiebre alta, tos, posible caso de COVID",
});

Es genial esto de poder decir que campos son obligatorios, pero me hace falta más "chicha", quiero forzar a que ciertos campos sean de un tipo dado, o que estén dentro de un rango, o de una enumeración de valores ¿Puedo hacer eso? Si, veamos como.

Ahora que tenemos el validation schema definido, lo que queremos hacer es modificarlo, para ello ejecutamos esta vez runCommand, le indicamos colección y los validadores a aplicar (ojo esto machaca a la configuración anterior, debemos de arrastrar los datos de la configuracíon antigua).

db.runCommand({
  collMod: "consultas",
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["nombre", "edad", "especialidad", "diagnostico"],
      properties: {
        nif: {
          bsonType: "string",
          pattern: "^[0-9]{8}[A-Z]$",
          description:
            "El formato de nif es 8 digitos seguidos de letra en mayuculas, sin separadores ni espacios",
        },
        nombre: {
          bsonType: "string",
          description:
            "Debe informar el campo nombre y este debe ser un string",
        },
        edad: {
          bsonType: "int",
          minimum: 0,
          maximum: 120,
          description:
            "El campo edad debe ser un número y estar comprendido entre 0 y 120",
        },
        especialidad: {
          bsonType: "string",
          enum: ["general", "pediatria", "neurologia"],
          description:
            "El campo especilidad debe ser uno de estos tres valores: general, pediatria, neurologia",
        },
      },
    },
  },
});

Vamos a probar a insertar varios documentos erroneos y ver que mensajes recibimos:

Un Nif no valido

db.consultas.insertOne({
  nif: "234",
  nombre: "Paco Mal Nif",
  edad: 23,
  especialidad: "general",
  diagnostico: "Migrañas",
});

Si quieres ver como funciona con un nif valido, cambia el valor del campo nif por: 12345678X

Una edad imposible

db.consultas.insertOne({
  nombre: "Ana Anciana",
  edad: 223,
  especialidad: "general",
  diagnostico: "Migrañas",
});

Para poder insertar este documento, puedes cambiar el valor del campo edad por un 23.

Una especialidad que no aplica

db.consultas.insertOne({
  nombre: "Manuel Olores",
  edad: 40,
  especialidad: "perfumeria",
  diagnostico: "Migrañas",
});

Para poder insertar este documento, puedes cambiar el valor del campo especialidad por un neurologia .

Vamos a probar ahora a insertar una entrada correcta:

db.consultas.insertOne({
  nif: "12345678X",
  nombre: "Javier Garcia",
  edad: 45,
  especialidad: "general",
  diagnostico: "Arritmias, acompañado de tensión alta",
});

La validación de esquemas de MongoDB, ofrece muchos más funcionalidad, si quieres seguir profundizando aquí tienes unos enlaces interesantes:

Una cosa importante, está validacíon de esquemas, sirve para tener una última frontera y evitar introducir entradas erróneas, es recomendable que también realicemos estás validaciones a nivel de nuestra aplicación.

¿Con ganas de aprender Backend?

En Lemoncode impartimos un Bootcamp Backend Online, centrado en stack node y stack .net, en él encontrarás todos los recursos necesarios: clases de los mejores profesionales del sector, tutorías en cuanto las necesites y ejercicios para desarrollar lo aprendido en los distintos módulos. Si quieres saber más puedes pinchar aquí para más información sobre este Bootcamp Backend.