MongoDB

MongoDB ist die führende Open-Source, Document Datenbank die für einfache Entwicklung und Skalierung aber auch für Big Data Szenarien entwickelt wurde.

JSON Schema Validierung - Ein Datenmodell auf clevere Art festlegen

Marc-David Militz
Expert
  • Artikel von Ken W. Alger

    • englischer Originalartikel
      https://www.mongodb.com/blog/post/json-schema-validation--locking-down-your-model-the-smart-way
      Übersetzung mit freundlicher Genehmigung von MongoDB


      In früheren Beiträgen habe ich die Flexibilität des Document Data Models in MongoDB bereits näher erläutert.
      Dieses hat viele Vorteile, wenn es darum geht Anwendungen schnell zu erstellen und sich dabei nicht an eine starre Datenstruktur gebunden zu sein, wie man sie in einer Legacy Datenbank mit einer relationalen Engine hat.
      Wenn das Datenbank Schema einmal beschlossen wurde, dann ist es oftmals nützlich dies fest zu verankern.
      In MongoDB kann man dafür die JSON Schema Validierung nutzen.
      Bereits seit der Version 3.6 ist es möglich Schema Validierung, basierend auf der JSON Schemas Daft Specification, zu nutzen.
      http://json-schema.org/
      https://docs.mongodb.com/manual/core/schema-validation/

      Die Möglichkeit, das Document Data Model mit einem festgelegten Schema festzulegen bedeutet z.B., dass es möglich ist Meilensteine in der Entwicklung des Datenmodells zu definieren, gegen die man auch Tests fahren kann.
      Ein potenzielles Szenario wäre der Punkt, an dem ein Anwendung einen Entwicklungszyklus durchlaufen hat und das Datenmodell etwas starrer geworden ist.
      An diesem Punkt sorgt ein definiertes Datenmodell dafür, dass keine unbeabsichtigten Änderungen am Schema gemacht werden oder Felder einen falschen Datentyp enthalten.
      Man verhindert damit ganz einfach, dass jemand beispielsweise ein Bild in einem Passwortfeld speichert.

      Schema Validierung kann in MongoDB sowohl beim Erstellen einer Collection, als auch auf bereits existierende Dokumente angewendet werden.
      Der Validierungsprozess findet beim Einfügen und updaten der Dokumente statt.
      Aus diesem Grund werden bereits in einer Collection vorhandene Dokumente erst validiert, wenn sie geupdated werden.
      Die Syntax für das Implementieren der Validierung ist, in beiden Fällen, relativ einfach.

      • Neue Collection

        • db.createCollection("recipes",
          validator: {
          $jsonSchema: {
          <<Validation Rules>>
          }
          }
          )


          • Existierende Collection

            • db.runCommand( {
              collMod: "recipes",
              validator: {
              $jsonSchema: {
              <<Validation Rules>>
              }
              }
              } )


              Innerhalb der Validator-Sektion des Dokumentes können wir explizit alle Felder aufführen, die das Dokument haben muss.
              Wir können festlegen welche Werte die Felder enthalten dürfen, Minimum und/oder Maximum Werte Felder und ob es erlaubt ist dem Dokument weitere Felder hinzuzufügen.
              Ein Beispiel mit einigen dieser Features wird helfen, die Funktionen etwas klarer zu machen.

              • JSON Schema Validierung

                • Stellen wir uns, für das Beispiel, eine Collection mit Kochrezepten vor.
                  Die grundlegende Information, die wir benötigen, ist der Name des Rezeptes, die Anzahl der Portionen und eine Liste von Zutaten.
                  Dies werden wir als Pflichtfelder festlegen.
                  Es darf optional ein Feld "cooking_method" geben, falls jemand nach einer bestimmten Art der Zubereitung suchen möchte.
                  Wir erstellen eine neue Collection und definieren unsere Validierungsregeln.
                  db.createCollection("recipes", {
                  validator: {
                  $jsonSchema: {
                  bsonType: "object",
                  required: ["name", "servings", "ingredients"],
                  additionalProperties: false,
                  properties: {
                  _id: {},
                  name: {
                  bsonType: "string",
                  description: "'name' is required and is a string"
                  },
                  servings: {
                  bsonType: ["int", "double"],
                  minimum: 0,
                  description:
                  "'servings' is required and must be an integer with a minimum of zero."
                  },
                  cooking_method: {
                  enum: [
                  "broil",
                  "grill",
                  "roast",
                  "bake",
                  "saute",
                  "pan-fry",
                  "deep-fry",
                  "poach",
                  "simmer",
                  "boil",
                  "steam",
                  "braise",
                  "stew"
                  ],
                  description:
                  "'cooking_method' is optional but, if used, must be one of the listed options."
                  },
                  ingredients: {
                  bsonType: ["array"],
                  minItems: 1,
                  maxItems: 50,
                  items: {
                  bsonType: ["object"],
                  required: ["quantity", "measure", "ingredient"],
                  additionalProperties: false,
                  description: "'ingredients' must contain the stated fields.",
                  properties: {
                  quantity: {
                  bsonType: ["int", "double", "decimal"],
                  description:
                  "'quantity' is required and is of double or decimal type"
                  },
                  measure: {
                  enum: ["tsp", "Tbsp", "cup", "ounce", "pound", "each"],
                  description:
                  "'measure' is required and can only be one of the given enum values"
                  },
                  ingredient: {
                  bsonType: "string",
                  description: "'ingredient' is required and is a string"
                  },
                  format: {
                  bsonType: "string",
                  description:
                  "'format' is an optional field of type string, e.g. chopped or diced"
                  }
                  }
                  }
                  }
                  }
                  }
                  }
                  });


                  Wenn wir einen Blick auf das werfen, was wir hier definiert haben, dann sehen wir die Pflichtfelder "name", "servings" und "ingredients".
                  Die Regel "additionalProperties: false" verhindert, dass, über diese drei Felder hinaus, weitere Felder eingefügt werden, die wir nicht explizit zugelassen haben.
                  Wir haben das "_id" Feld in unseren Dokumenten zugelassen, was natürlich wichtig ist.
                  Wenn wir dieses Feld nicht zulassen kann man in die Collection keine Dokumente einfügen, da "_id" automatisch befüllt wird und den Primärschlüssel des Dokuments darstellt.

                  Das Feld "name" wurde als Pflichtfeld mit einem String als Inhalt definiert.
                  Das Feld "servings" ist ein Pflichtfeld und darf Integer oder Double Werte enthalten.
                  Als nächstes gibt es das optionale "cooking_method" Feld. Für dieses ist, sofern es im Dokument vorhanden ist, eine Liste zulässiger Werte definiert.

                  Das Feld "ingredients" hat einiges an zusätzlicher Komplexität in seinem Validierungsprozess.
                  Es ist als Array von Elementen definiert, welche wiederun "quantity", "measure", und "ingredient" als Pflichtfelder haben müssen.
                  Optional ist hier das Feld "format" vorgesehen, wo man eine Beschreibung wie "im Ganzen", "gewürfelt", "gehackt" oder ähnliches einfügen kann.
                  Welche Datentypen, von den einzelnen Feldern, akzeptiert werden ist durch den Schema-Validierungsprozess vorgegeben. Double oder Decimal für "quantity", einer der vordefinierten Werte für "measure" und ein String für "ingredient" und "format".

                  Mir den aktivierten Validierungsregeln können wir nun einige Beispieldokumente in die Collection einfügen und sehen was passiert.

                  • Dokument 1

                    • db.recipes.insertOne({
                      name: "Chocolate Sponge Cake Filling",
                      servings: 4,
                      ingredients: [
                      {
                      quantity: 7,
                      measure: "ounce",
                      ingredient: "bittersweet chocolate",
                      format: "chopped"
                      },
                      { quantity: 2, measure: "cup", ingredient: "heavy cream" }
                      ]
                      });

                      Das Einfügen funktioniert, da alle Pflichtfelder innerhalb der Validierungsregeln vorhanden und befüllt sind.

                      • Dokument 2

                        • db.recipes.insertOne({
                          name: "Chocolate Sponge Cake Filling",
                          servings: 4,
                          ingredients: [
                          {
                          quantity: 7,
                          measure: "ounce",
                          ingredient_name: "bittersweet chocolate",
                          format: "chopped"
                          },
                          { quantity: 2, measure: "cup", ingredient: "heavy cream" }
                          ],
                          directions:
                          "Boil cream and pour over chocolate. Stir until chocolate is melted."
                          });

                          Das Einfügen dieses Dokuments wird mit der Fehlermeldung "WriteError: Document failed validation" fehlschlagen, weil es das zusätzliche Feld "directions" enthält.

                          Es gibt noch eine ganze Reihe weiterer Regeln, die man auf Dokumente anwenden kann
                          https://docs.mongodb.com/master/reference/operator/query/jsonSchema/#doc-insert-schema-validation
                          außerdem kann man die Schema-Validierung auch auf Subdokumente, wie wir das mit den "ingredients" gemacht haben, und auf Arrays anwenden.
                          Zudem kann man Schema-Abhängigkeiten setzen, um Applikationslogik nativ in der Datenbank zu verankern.
                          Des Weiteren lässt sich die "validation strictness" beeinflussen, was es erlaubt festzulegen ob es einen Fehler oder nur eine Warnmeldung gibt.
                          https://docs.mongodb.com/manual/core/schema-validation/#specify-validation-rules

                          • Zusammenfassung

                            • JSON Schema Validierung ist ein mächtiges Werkzeug, um die Integrität der Datenstruktur zu gewährleisten.
                              Im Zusammenspiel mit dem Document Model von MongoDB hat man sogar noch viel mehr Möglichkeiten.
                              Wir haben die Möglichkeit schnell, verschiedene Schema Designs in einer Applikation auszuprobieren und, sobald wir ein Model festgelegt haben, dafür sorgen, dass diese Standards forciert werden.
                              Auf diese Weise nutzen wir die Vorteile sowohl der Flexibilität des Document Models als auch der Datenvalidierung.

                              Wenn sie sich zu den Qualiero Angeboten zum Thema MongoDB informieren wollen, so haben sie hier dazu die Möglichkeit
                              https://www.qualiero.com/glossar/mongodb.html

Latest member activities

Tags

Recommend this community post