MongoDB

Was ist die MongoDB?

Ist eine dokumentenorientiertes NoSQL-Datenbankmanagementsystem des Unternehmens MongoDb, Inc. Der Quellcode ist Open Source und unter der proprietären Server Side Public License (SSPL) verfügbar. Der Name leitete sich aus dem engl. humongous für "gigantisch" ab und symbolisiert so die immense Speicherfähigkeit der Datenbank. Die Daten werden in einem JSON-ähnlichen Dokument gespeichert. Dadurch ist eine Modellierung komplexer Daten in ihrer natürlichen Hierarchie möglich. Der Inhalt der Dokumente innerhalb einer Kollektion kann theoretisch unterschiedlichster Natur sein, wodurch eine hohe Flexibilität bei der Entwicklung und Datenhaltung ensteht. So werden ganze Datensätze in einem einzigen Dokument gespeichert und sind gleichzeitig abrufbar und indizierbar. Die Schreiboperation eines kompletten Datensatzes ist nur auf ein einzelnes Dokument beschränkt und dadurch Atomar durchführbar. Da nur ein einziges Dokument und nicht die gesamt Kollektion bei einem Schreibvorgang blockiert wird, ist eine hohe Parallelität beim Bearbeiten der Daten möglich und eine hohe Zugriffsgeschwindigkeit auf die Daten garantiert. Dieser Aufbau und diese Flexibilität ist ideal um die Vielzahl an Informationen und die sich verändernden Strukturen der Metadaten im OER, LOM und LRMI - Kontext abbilden zu können.  


MongoDB Cluster aufbau mit Replicaset und Shards


Inhalt dieser Seite


Mitwirkende an dieser Seite:

UserEditsCommentsLabels
Sebastian Wollner 2400
Matthias Hupfer 200
Herr Torsten Simon 100
Herrmann (WLO-Kernteam) Nina 100


Die MongoDB wurde von Grund auf als Cluster konzeptioniert. Sie kann als einzelne Instanz oder in einem Clusterverbund, bestehend aus vielen Knoten, betrieben werden. Im Cluster kann die MongoDB in unterschiedlichen Modi laufen. So können einzelne MongoDB Instanzen als Replica Sets dienen, um eine höhere Daten- und Zugriffssicherheit bei Ausfällen zu gewährleisten und einen Datenverlust zu vermeiden. Im Sharding Modus werden die Daten einer Kollektion auf mehrere Knoten verteilen, wodurch die Last einer einzelnen Instanzen auf viele Instanzen Aufgeteilt wird. Diese beiden Mechanismen stehen für eine hohe horizontale Skalierbarkeit und Ausfallsicherheit.  

Weiter ist aufzuführen, dass No-SQL Datenbanken und im speziellen die MongoDB der State of the Art in Sachen verteilter Datenbanken ist. Dies ist auch daraus ersichtlich, dass die MongoDB als SaaS von vielen großen Cloud-Dienstleistern, u.a. von Amazon Web Services, Google-Cloud und Microsoft Azure, angeboten wird und mittlerweile von namhaften Unternehmen wie Toyota, Forbes, SAP und vielen weiteren eingesetzt wird.  Natürlich lässt sich die MongoDB auch als Self-Hostet Lösung in einem eigenen Server Cluster mit eigener Infrastruktur betreiben. 

Jedes System hat jedoch auch Schwachstellen. So können Beziehungen zwischen Dokumenten zwar abgebildet werden, jedoch sind diese Abfragen wesentlich langsamer als bei einer relationalen Datenbank. Auch verfügt die MongoDB über keine Foreign-Key-Constraints. Diese prüfen bei einer relationalen Datenbanken, ob eine Relation zu einem oder mehreren Einträgen besteht. Ist dies der Fall, kann z.B. der Fremdschlüssel des Verweisenden Eintrages zurückgesetzt werden, der gesamte Löschvorgang abgebrochen werden oder kaskadierend alle in Beziehung stehende Einträge und dessen Verweise gelöscht werden. Da dieses Konzept in gänze Fehlt, kann es zu Datenverlust und inkonsistenten Zuständen kommen. Auch Transaktionen würden die Leistung der Datenbank beim Schreiben von mehrerern Dokumenten einschränken. Gerade im Hinblick auf das Sharding, wobei eine Transaktion über mehrere Rechner erfolgen kann, ist ein erheblicher Mehraufwand beim Speichervorgang von Nöten. Daher sollten intensive Beziehungen zwischen Dokumenten, wie bei einer relationalen Datenbank, eher vermieden werden. Ein weiterer Nachteil liegt darin, dass die maximale Größe eines Dokumentes nur bei 16MB liegt, was streng genommen relativ viel ist und in den meisten Fällen auch ausreichen wird. Dieses lässt sich durch den GridFS Mechanismus zwar erweitern, schränkt aber auch hier den Funktionsumfang und die Geschwindigkeit der MongoDB ein.  



Proof of Concept

In einem Proof of Concept sollte herausgefunden werden, wie sich die MongoDB in die bestehende Software intigrieren lässt, welche Auswirkungen dies auf die Geschwindigkeit hat und wie die Metadaten, LOM und LRMI konform gespeichert werden können. Die Daten der PostgreSQL wurden analysiert und nach den Kriterien der Häufigkeit, Größe und Verarbeitungsdauer herausgelöst.  Zu diesen gehören Daten gehören: Dateien (IO), Sammlungen (Map), Remote-Objekte (RemoteObject), und geteilte Inhalte (Shared). 


Metadaten

Die Metadaten eines Datentypes werden pro Knoten in einem MongoDB Dokument gespeichert. Hierbei wird eine LOM und LRMI konforme Speicherweise angestrebt, um den Datenaustausch mit Fremdsystem zu vereinfachen. Neben den LOM und LRMI Daten werden noch systemrelevante Daten in dem Dokument gespeichert.  Aufgrund des flexiblen Dokumentenaufbaus werden alle Datentypen in die gleiche Kollektion geschrieben. Das hat zum Vorteil, dass mehrere Knoten in einer Batchanweisung, also als Block, abgefragt werden können, ohne vorher den Typ zu überprüfen, um dann die einzelnen Kollektionen abzufragen. 

Zusätzlich zu diesen Informationen, versioniert Alfresco die Metadaten eines Knotens, so dass zwei Kollektionen in der MongoDB benötigt werden. Eine Kollektion in der alle Dokumente mit den aktuell gültigen Metadatensatz gespeichert werden und eine Kollektion mit den unterschiedlichen Versionen. Dies hat zum Vorteil, dass die Größe der Indizes der Kollektion proportional zur Anzahl der Dokumente wächst, wodurch die Abfragegeschwindigkeit weniger stark beeinträchtigt wird.  Die Metadaten einer bestimmten Versionen hingegen, werden sehr selten abgefragt und können deshalb ohne Probleme in einer separaten Kollektion ausgelagert werden.   

Das Dokument selber ist in diverse Unterobjekte untergliedert. Je nach Anwendungszweck und Informationstyp sind sie im Dokument vorhanden. So werden beispielsweise alle Educational-Metadaten unter lom gespeichert, welches sich an das LOM Model orientiert. Andere Unterobjekte wie z.B. aspects, association, store und co sind eher technischer Natur und werden vom System zur Verwaltung der Daten und Inhalte benötigt. Wiederum andere sind Typabhängig und werden nur bei bestimmten Typen hinzugefügt. Prinzipiell wird das Ziel verfolgt nur die Notwendigen Objekte anzulegen, die wirklich benötigt werden. Dies reduziert den Speicheraufwand bei Millionen von Daten erheblich. 


Beispiel: Auszug von Metadaten eines in der MongoDB gespeicherten IO Types
{
  _id: 'ccfa9de7-7a5b-4a94-a368-8647fda6a9fd',
  nodeType: '{http://www.campuscontent.de/model/1.0}io',
  aspects: [
    '{http://www.campuscontent.de/model/lom/1.0}lifecycle',
    '{http://www.campuscontent.de/model/1.0}eduscope',
    '...'
  ],
  association: {
    original: { id: 'ccfa9de7-7a5b-4a94-a368-8647fda6a9fd' }
  },
  store: {
    dbId: 1031,
    id: 'SpacesStore',
    protocol: 'workspace'
  },
  lom: {
    general: {
      title: 'Marseille',
      description: [ 'Marseille, die heimliche Hauptstadt des Mittelmeers, ...' ],
      language: ['de','en'],
      keyword: ['Hafen','Hafenstadt','Infrastruktur', '...'],
      structure: { value: 'atomic' },
      aggregationLevel: { value: '1' }
    },
    lifecycle: {
      version: '1.0',
      status: 'final',
      contribute: [
        {
          role: 'publisher',
          content: [ 'BEGIN:VCARD\nVERSION:3.0...' ]
        }
      ]
    },
    technical: {
      duration: '00:43:00'
    },
    educational: [
      {
        context: [
          { value: 'compulsory education' },
          { value: 'continuing education' },
          { value: 'lower secondary school' }
        ],
        intendedEndUserRole: [
          { value: 'learner' },
          { value: 'teacher' }
        ],
        typicalAgeRangeNominal: {
          from: 13,
          to: 15
        }
      }
    ],
    rights: {
      cost: { value: true },
      copyrightAndOtherRestrictions: { value: true },
      description: 'abc-Availability:restricted_mz'
    },
    classification: [
      {
        purpose: 'learningGoal',
        taxon: [
          { value: '220110201' },
          { value: '2201902' }
        ]
      }
    ]
  },
  remote: {
    location: 'REPLICATION',
    repository: { id: 'SOME ID' },
    id: 'XYZ_ID',
    timestamp: '2022-02-23T08:14:20Z'
  },
  version: {
    version: '1.0',
    autoCreateVersion: false
  },
  affiliation: {
    context: [ 'default' ]
  },
  info: {
    creator: 'admin',
    createDate: ISODate('2022-03-01T14:50:15.412Z'),
    modifier: 'admin',
    modifiedDate: ISODate('2022-03-01T14:50:15.412Z'),
    filename: 'Marseille',
    propagateMetadataset: false,
    metadataset: 'default',
    objectType: { value: '0' },
    preview: { url: 'SomeURL.jpg' }
  },
  alfmap: {
    '{http://www.alfresco.org/model/content/1.0}initialVersion': false,
    '...'
  }
}

Integration in edu-sharing

Die Integration der MongoDB in das edu-sharing erfolgt zweistufig. Damit bestehende Systeme nicht sofort geändert werden müssen, wurde ein neuer Mongo Node Service entwickelt, der das bestehende System nach außen unverändert repräsentiert. Dabei wurde der zentrale Node Service Dienst, welcher die Metadaten eines Knotens aus Alfresco bzw. der PostgresSQL ließt und schreibt, durch den Mongo Node Service ersetzt. Dieser erbt von Node Services und greift an den relevanten Stellen ein und überschreibt die bestehende Funktionalität. Da die Metadaten aus der MongoDB einen anderen strukturellen Aufbau haben als die von Alfresco, wurde noch ein zusätzlicher Mapping Service hinzugefügt. Dieser Transformiert mithilfe der JOLT Bibliothek die Daten zwischen den unterschiedlichen Schemata. 

Bei der Abfrage von Metadaten wird als erstes die MongoDB angesprochen, findet diese kein Dokument, wird die Abfrage weiter an Alfresco geleitet. Es hat sich gezeigt, dass dies schneller ist, als wenn man vorher eine Typ-Abfrage startet und dann auf Basis dessen entscheidet, welche Datenbank verantwortlich ist, da ohnehin die Datenlast bei der MongoDB liegen wird. Die von der MongoDB gelieferten Daten werden in einem weiteren Schritt mit den Laufzeitdaten ergänzt. Also jenen, die dynamisch erzeugt werden, wie z.B. Rechteabhängige Links etc. 

Der Schreibvorgang von Metadaten sieht hingegen vor, dass die Daten immer zuerst im Alfresco gespeichert werden und dann aus dem Alfresco in die MongoDB kopiert werden. Dies hat zum einen den Hintergrund, dass diverse Interzeptoren die Daten noch ändern können und zum anderen soll die Datenintegrität vorerst im Alfresco gewahrt werden. Interozeptoren können im aktuellen Stand noch nicht vom Mongo Node Service abgefangen werden. Ein weiteres Problem sind Transaktionen im Alfresco.  Da mehrere Befehle innerhalb einer Transaktion vom Node Service behandelt werden können, kann es bei einem Rollback, einer schreibenden Transaktion, zu Dateninkonsistenz zwischen Alfresco und der MongoDB kommen. Die MongoDB ist in diesem POC nocht nicht in das Transaktionssystem von Alfresco eingebunden. Schreibbefehle werden sofort ausgeführt, bei einem Rollback der Transaktion bleiben also die geschriebenen Daten in der MongoDB vorhanden, wohingegen die Daten im Alfresco zurück gerollt werden. Dieses Problem erfordert mehrere Umbaumaßnahmen die im Rahmen weiterer Entwicklungsschritte umgesetzt werden müssen. 

Auch werden Aufgrund der bisherigen Datenhaltung im Alfresco, die Metadaten in mehreren Abfragen zusammengebaut, wodurch das gleiche Dokument mehrfach von der MongoDB abgerufen wird. Dieses Problem wird in der zweiten Stufe der MongoDB Integration behoben. Dabei werden die Services sowie das Frontend so umgebaut, dass diese mit den Daten aus der MongoDB direkt arbeiten können. Dies hat zur Folge das weniger abfragen an die MongoDB gestellt werden und die Daten bereits in der richtigen Struktur vorhanden sind und nicht erst in das passende Format umgewandelt werden müssen. Dies wird in den kommenden Entwicklungsstufen ebenfalls umgesetzt.

Datenmapping zwischen Alfresco und MongoDB