Moin moin und hallo,

in diesem ersten kleinen Tutorial, zu diesem Thema, möchte ich auf Mongo DB und die grundsätzlichen CRUD Operationen eingehen.


Ziel

Dieses soll der erste Artikel einer kleinen Reihe sein, die ich aufeinander aufbauend fortschreiben und schlussendlich mit den Aggregationen und Abfragen von verschachtelten Werten beenden werde.

Ich werde im Folgenden erstmal grundsätzliches zu Mongo DB sagen und die Basis-Operationen (Create, Update, Read, Delete) beschreiben.

Motivation zu Mongo DB

Warum sollte man überhaupt Mongo DB einsetzen? Es gibt doch zahlreiche SQL Datenbanken!

Tatsächlich ist Mongo DB eine Datenbank, die man der Gruppe von NoSQL zuordnet.

Die Idee ist, dass man Datensätze nicht länger als Tabellen sondern als viel mehr Dokumente versteht.

Es war auch für mich eingangs nicht so einfach den Unterschied zu durchdringen, aber ich habe einen Zugang gefunden.

Tabellen kann man wie folgt verstehen:

  • Tabellen sind “flach”
  • Es gibt zwei Dimensionen: Spalten und Zeilen
  • Komplexe Abfragen laufen daruaf hinaus, dass man mehrere Tabellen an einander reiht, wieder zu einer flachen Tabellen-Struktur
  • Noch Komplexere Abfragen und Prozesse, z.B. das Kopieren von einem kontruierten Datensatz, die Einrichtung von Zwischen-Tabellen oder temporären Datenhaltern

Dokumente sehe ich dagegen wie folgt:

  • Dokumente haben Eigenschaften, ähnlich wie Objekte
  • Eine Eigenschaft hat einen Wert
  • Eine Eigenschaft kann selbt ebenfalls ein Objekt oder eine Liste von Objekten beinhalten
  • Auch Dokumente können mit einander verknüpft werden um komplexe Fälle abzubilden

**Was heißt das jetzt?**

Nun die einfachste Gegenüberstellung, die ich mir vorstlelen kann ist das Tabellen eben Tabellen sind und Dokumente JSON-Objekte.


#### Tabelle “`sql | Name | Strasse | Plz | Ort —————————————– | Max | Olmweg | 30455 | Hannover | Bernd | Blumen Allee | 30167 | Hannover “`
#### Dokumente
[
    {
        Name: 'Max',
        Strasse: 'Olmweg',
        Plz: '30455',
        Ort: 'Hannover',
        tel: ['12345', '98765']
    },
    {
        Name: 'Bernd',
        Strasse: 'Blumen Allee',
        Plz: '30167',
        Ort: 'Hannover'
    }

]

Und was bringt mir das?

Wie man sehen kann, eigent sich Mongo DB hevorragend dafür heterogene Datensätze zu verarbeiten und dabei trotzdem produktiv zu sein.

In dem obigen Beispiel sieht man, dass ein Benutzer mehrere Telefonummern hat, ein anderer wieder nicht.

Man könnte diesen Fall auch in SQL abbilden, nur nicht ganz so einfach.

In keinem der Projekte, wo ich Mongo DB eingesetzt habe, hatte ich je Probleme mit Datenbankseitigen Erweiterungen.

Bei SQL hingegen muss man stets darauf achten, dass man seine Migrations-Skripte schreibt und diese auch iterativ aufeinander aufbauen.

In Mongo DB setze und nutze ich einfach eine bestimmte Eigenschaft, Objekt oder Datenbank wenn ich sie brauche und auf magische Weise ist es dann verfügbar.

Datenbank anlegen

Wie man Mongo DB lokal oder auf einem Server installiert ist in der offziellen Dokumentation sehr gut beschrieben und möchte ich hier nicht noch einmal breit treten.

Ich möchte dirket auf der Konsole mit einer neuen Datenbank starten.

roman@roman:~$ mongo userDb
MongoDB shell version: 3.2.9
connecting to: userDb
>

Schon haben wir eine neue Datenbank bereit und befinden uns in der Konsole von Mongo DB (aka. Mongo Shell)

Wenn wir uns nun alle vorhandenen Kollektionen anzeigen lassen, sehen wir natürlich erstmal nichts überraschend:

> show collections
> 

Eine Kollektion kann man wie die Definition oder Gruppe von Dokuemnten verstehen (bzw. Tabelle in SQL).

Ein Dokument ist ein konrketer Datensatz aus einer Kollektion, sprich wie eine Zeile in einer SQL-Tabelle.

Eine Mongo DB Kollektion / Dokument anlegen (Create)

Wie legt man nun ein Dokument an? In dem man einfach in solches Daten rein schreibt:

> db.user.insert( {
        Name: 'Max',
        Strasse: 'Olmweg',
        Plz: '30455',
        Ort: 'Hannover',
        tel: ['12345', '98765']
    })

WriteResult({ "nInserted" : 1 })
>

Wenn man sich jetzt die Kollektionen anzeigen lässt, tauchen aufeinmal zwei Einträge auf:

> show collections
system.indexes
user
> 

Der zweite sollte auch wenig überraschen, der erste hingegen wird automatisch vom System erzeugt und gepflegt.

Mit Hilfe des Indexes kann die Historie und Indezierung unserer Kollektionen nachverfolgen. Zu Beginn sieht sie wie folgt aus:

> db.system.indexes.find()
{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "userDb.user" }
> 

Lese-Operation (Read)

Wie man Daten abfragt habe ich nun schon paar Zeilen oben drüber verraten.

Will man einen bestimmten Datensatz abfragen, muss man diesen von dem db Objekt anfordern.

Ganz recht, die Abfrage funktioniert wie ein Funktions-Aufruf in JavaScript.

Man kann auch eigene Funktionen definieren und verrückte Sachen damit anstellen, auf die ich aber in einem späteren Artikel erst eingehen werde.

Fragen wir doch zunächst erstmal ganz allgemein unsere User DB ab:

> db.user.find()
{ "_id" : ObjectId("57db962b1657f674ac2e727d"), "Name" : "Max", "Strasse" : "Olmweg", "Plz" : "30455", "Ort" : "Hannover", "tel" : [ "12345", "98765" ] }
> 

Wie man sehen kann wurde auch automatisch eine UUID für unseren Datensatz eingetragen.

Was passiert, wenn ich nur den Namen und die Telefonummern angezeigt haben möchte?


Nun dafür müssen wir unsere Query erweitern:
> db.user.find({}, {Name:1, tel:1})
{ "_id" : ObjectId("57db962b1657f674ac2e727d"), "Name" : "Max", "tel" : [ "12345", "98765" ] }
>

Die Eigenschaft _id wird dabei immer ausgegeben, was aber nicht stört, sondern so gut wie immer von Vorteil ist, wenn man mal mit echten Daten in einem Projekt arbeitet.

Die find()-Funktion kennt zwei Parameter:

  1. Das Query-Objekt

    • Alle Einschränkungen bzgl. der Abfrage werden hier definiert
  2. Das Ausgabe-Parameter-Objekt

    • Durch das setzen des Flags 1 weiß Mongo DB welche Parameter ausgegeben werden sollen

Erweitern wir mal unsere Kollektion um einen Eintrag:
> db.user.insert( {
        Name: 'Bernd',
        Strasse: 'Blumen Allee',
        Plz: '30167',
        Ort: 'Hannover'
    })

WriteResult({ "nInserted" : 1 })
>

Wie erfrgat man nun den nur den neuen Datensatz?

z.B. anhand des Namens:

> db.user.find({Name: 'Bernd'})
{ "_id" : ObjectId("57db9fd21657f674ac2e7280"), "Name" : "Bernd", "Strasse" : "Blumen Allee", "Plz" : "30167", "Ort" : "Hannover" }
> 

Aktualisierung (Update) Operation

Nun stellen wir fest, dass wir doch die Telefonnummer von Bernd kennen und diese dem Datensatz anfügen möchten.

Dafür gibt es bie Mongo DB eine update()-Funktion.

Diese Funktion kennt drei Parameter:

  1. Das Query-Objekt

    • Welche Datensätze sollen aktualisiert werden?
  2. Das Parameter-Objekt

    • Welche Daten sollen geändert werden?
  3. Das Optionen-Objekt

    • Wie soll die Operation durchgeführt werden?
> db.user.update({"_id" : ObjectId("57db9fd21657f674ac2e7280")}, {$set: {tel: "654789"}}, {})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> 

Wichtig ist hier vorallem der $set-Operator. Denn man könnte auch irgendein Objekt ohne das $set einsetzen und damit seinen ganzen Datensatz überschreiben.

Fragen wir dochmal nun unsere Daten ab:

> db.user.find()
{ "_id" : ObjectId("57db962b1657f674ac2e727d"), "Name" : "Max", "Strasse" : "Olmweg", "Plz" : "30455", "Ort" : "Hannover", "tel" : [ "12345", "98765" ] }
{ "_id" : ObjectId("57db9fd21657f674ac2e7280"), "Name" : "Bernd", "Strasse" : "Blumen Allee", "Plz" : "30167", "Ort" : "Hannover", "tel" : "654789" }
> 

Wie man sehen kann ist die Telefonnummer in einem Fall eine Lsit eund im anderen Fall ein String. Das ist eine der großen Stärken von Mongo DB, birgt aber auch Gefahren in der Programmierung.

Wenn sich Entwickler nicht vorher Gedanken machen, wann welches Format wo verwendet wird, kann es langfristig die Bildung von sehr shclechtem Code begünstigen.


Lösch (Delete) Operation

Kommen wir zum letzten Teil, dem Löschen.

Hier gibt es grundsätzlich nichts außergewöhnliches:

> db.user.remove({Name: 'Max'})
WriteResult({ "nRemoved" : 1 })

> db.user.find()
{ "_id" : ObjectId("57db9fd21657f674ac2e7280"), "Name" : "Bernd", "Strasse" : "Blumen Allee", "Plz" : "30167", "Ort" : "Hannover", "tel" : "654789" }
> 

Fazit

Ich in diesem ersten Mongo DB Tutorial habe ich das Thema Mongo DB nur sehr grob umschrieben. Insbesondere bei der find() und update() Funktion gibt es soviel zu wissen, wenn es später auch um Aggregation geht, dass ich dafür jeweils einen eigenen Artikel schreiben werde.

Allerdings sollte allgemein klar geworden sein wie Mongo DB CRUD Operationen umsetzt.

Hoffentlich hast du nun einen Einstieg in Mongo DB bekommen und möchtest tiefer in die Materie einsteigen.

Solltest du bereits jetzt schon mehr Futter wollen, so lege ich dir Buch “Mongo DB: The Definitiv Guide ans Herz:

Neben sämtlichen Grundlagen was die Abfrage-Sprache angeht, behandelt das Buch auch weiterführende Thmen, wie Scaling, Recovery und allgemein Cluster bezogene Anwendungsfälle, in all ihren Untiefen.


#### In diesem Sinne, bis demnächst!