Schéma de validation MongoDB

Quand on utilise MongoDB, les collections peuvent facilement contenir des types de données différents pour le même champ. Comment assurer qu’un champ soit toujours du même type ? Le schéma de validation MongoDB introduit dans la version 3.6 devrait nous aider.

Créer un schéma

Prenons pour l’exemple une collection evenements comprenant les champs suivant :

  • name, obligatoire, de type string
  • free, obligatoire, de type boolean
  • type, obligatoire, de type énumération
  • seats, facultatif, de type int ou long
db.createCollection("evenements", {
   validator: {
      $jsonSchema: {
         bsonType: "object",
	 additionalProperties: false,
         required: [ "name", "free", "type"],
         properties: {
	    _id: {},
            name: {
               bsonType: "string",
               description: "must be a string and is required"
            },
            free: {
               bsonType: "bool",
               description: "must be a boolean and is not required"
            },
            type: {
               enum: [ "Stage", "Competition", "Gala"],
               description: "can only be one of the enum values and is required"
            },
            seats: {
               bsonType: ["int", "long"],
               minimum: 0,
               maximum: 1000,
               exclusiveMaximum: false,
               description: "must be a short or long integer in [0, 1000]"
            }
         }
      }
   }
})

Le schéma ainsi décrit est fermé: additionalProperties: false. Cela veut dire qu’il est impossible d’ajouter des champs supplémentaires. En mettant additionalProperties à true, le schéma est appliqué aux champs décrits et il est possible d’en ajouter d’autres.

Insertion de document

// document valide
db.evenements.insert({ 
    "name": "Monte Carlo Fighting Trophy 2018", 
    "free": false,
    "type": "Gala"
});

// document invalide : tags
db.evenements.insert({ 
    "name": "Octogone 2", 
    "free": false,
    "type": "Gala",
    "tags": ["K1","Pancrase"]
});

Appliquer un schéma à une collection existante

?? quid si la collection contient des données non valides contre le schéma ??

db.runCommand({
  collMod: "oldEvenements",
  validator: {
    $jsonSchema: {
      // le schema
    }
  }
});

Voir le schéma appliqué à une collection

db.getCollectionInfos({name:"evenements"})

Le schéma est visible dans le champ options.validator.$jsonSchema

Un schéma validant des éléments imbriqués

Un document peut contenir des tableaux d’éléments complexes et les schémas permettent de les décrire aussi.

Pour l’exemple, admettons qu’un événement de boxe contienne de 1 à 10 combats entre 2 combattants sur 3 à 12 rounds.

db.createCollection("fightnights",{
    validator: {
      $jsonSchema: {
        bsonType: "object",
        required: ["fights"],
        properties: {
	fights: {
              bsonType: ["array"],
              minItems: 1,
              maxItems:10,
              items: {
                  required: ["redcorner", "bluecorner", "nbround"],
                  bsonType: "object",
                  additionalProperties: false,
                  properties: {
                      redcorner: {
                        bsonType: "string",
                        description: "'redcorner' must be a string and is required"
                      },
                      bluecorner: {
                        bsonType: "string",
                        description: "'bluecorner' must be a string"
                      },
                      nbround: {
                        bsonType: "int",
                        minimum: 3,
                        maximum: 12,
                        exclusiveMaximum: false,
                        description: "'nbround' must be an integer in [3, 12]"
                      },
                  }
              }
          }
        }
      }
    }
});

Le schéma appliqué à la collection fightnights permet de valider l’insertion des éléments suivants :

db.fightnights.insert({
        fights: [
            {
                redcorner: "Peter Aerts",
                bluecorner: "Jerome Le Banner",
                nbround: NumberInt(5),
            },
            {
                redcorner: "Ernesto Hoost",
                bluecorner: "Jerome Le Banner",
                nbround: NumberInt(5),
            },
            {
                redcorner: "Sam Greco",
                bluecorner: "Mirko Cro Cop",
                nbround: NumberInt(5),
            }
        ]
})

Cette fonctionnalité permet d’avoir des données plus saines en échange d’un peu de flexibilité. Il est possible d’aller plus loin avec la validation de schéma JSON et cela sera pour un prochain article.

Références

JSON Schema Validation – MongoDB