Hierarchische Daten in einer Graph-Datenbank

Einleitung

Im Beitrag „Hierarchische Daten in einer relationalen Datenbank“ habe ich geprüft, ob ich hierarchische Daten in eine relationale Datenbank zu klopfen. Das hat nur bedingt gut geklappt.

Dieses Mal probiere ich es mit Graphen-Datenbank.  Hier ist zunächst das Modell:

hierarchie-politischegebiete-150x150

Ich baue ein hierarchisches Modell auf Basis der politischen Ebenen des Landes Bayern auf. Ich möchte mit der Graphen-Datenbank dieselben Fragen klären, die ich im relationalen Modell klären wollte:

  • Ausgabe aller Bezirke von Bayern (RDBMS: leicht)
  • Alle Gemeinden des Landkreises Traunstein (RDBMS: leicht)
  • Gibt es eine politische Einheit mit dem Namen „Tutzing“? Wenn ja, wo in der Hierarchie befindet sich diese? (RDBMS: schwer)

Projekt-Setup

Für Tests habe ich eine Datenbank aufgebaut, mit der man die oben genannten Fragen live klären kann:

https://github.com/ollihoo/geographicalHierarchyGraph

Das Projekt hat im README eine Anleitung, wie man die Neo4j-Datenbank aufsetzt.

Aufbau der Datenbank

Die Datenbank nutzt Knoten, die die Hierarchie abbilden: (:Country), (:State), (:District), (:RuralDistrict), (:City), (:Community). Die zugehörigen Zuordnungen zur nächsthöhren Ebene werden durch :BELONGS_TO-Beziehungen abgebildet.

Zur Abfrage der Datenbank wird die Sprache Cypher benutzt, die in der Konsole des neo4j-Browsers angeboten wird.

Auswertung

Mit dieser Sprache lassen sich nun leicht die oben genannten Fragen beantworten:

Ausgabe aller Bezirke von Bayern

MATCH (d:Districts)-[:BELONGS_TO]->(s:State{name:"Bayern"}) return d.name

Als Ergebnis werden wie erwartet alle sieben Regierungsbezirke zurückgegeben.

Alle Gemeinden des Landkreises Traunstein

MATCH (c:Community)-[:BELONGS_TO]->(:RuralDistrict{name:"Traunstein"}) RETURN c.name

Es sollten 37 Gemeinden zurückgegeben werden.

Gibt es eine politische Einheit mit dem Namen „Tutzing“?

MATCH (n)-[:BELONGS_TO*1..]->(:State{name:"Bayern"}) 
WHERE n.name = "Tutzing"
RETURN n

Als Ergebnis sollte ein Community-Knoten zurück gegeben werden. Das heisst, es gibt eine Gemeinde namens „Tutzing“.

Wo in der Hierarchie befindet sich „Tutzing“?

Die Frage wurde bereits beantwortet (Tutzing ist eine Gemeinde), ich werde die Frage daher dahingehend erweitern, wie die einzelnen Hierarchie-Stufen aussehen:

MATCH path=(n)-[:BELONGS_TO*1..]->(:State{name:"Bayern"}) 
WHERE n.name = "Tutzing"
RETURN extract(node in nodes(path) | node.name)

Als Ergebnis wird ein Array zurück gegeben, das die einzelnen Hierarchie-Ebenen zurückgibt: [Tutzing, Starnberg, Oberbayern, Bayern]

Ergebnis und Ausblick

Im Vergleich zu einer relationalen Datenbank lassen sich die oben genannten Fragestellungen ohne größere Probleme lösen. Die expressive Sprache Cypher erlaubt eine eingängige Beschreibung der Knoten/Relationship-Muster und ermöglicht so, auch komplexere Fragen gut abbilden zu können.

Hier zunächst ein Vergleich der Elemente zwischen den beiden Modellen:

Element Relationales Modell Graphen-Modell
Entity/Dateneinheit Eine Zeile der Tabelle Knoten (z.B. (…) )
Typ der Dateneinheit Definiert durch Tabellen-Name Definiert durch die Label der Knoten (z.B. :State)
Eigenschaften der Entity Eine Tabellen-Zelle Eine property des Knotens (z.B. {name:“Bayern“})
Beziehung Kombination von Eigen- und Fremdschlüsseln, referenziert in Tabellen-Zellen Ein eigenes Relationship-element mit eigenem Label (z.B. -[:BELONGS_TO]-> )

Wie die Tabelle zeigt, arbeitet das Relationen-Modell sehr Tabellen-zentriert. Demgegenüber bietet das Graphen-Modell sehr viel mehr Modellierungs-Möglichkeiten an, die so komplexere Sachverhalte greifbarer machen.

Ausblick: in Hinblick auf den Abbildungsreichtum der Graphen-Datenbank stellt sich die Frage, warum relationale Datenbanken ein so zentrale Bedeutung bei zahlreichen Anwendungen haben. Eine Antwort ist, dass letztere sehr flexibel eingesetzt werden können und schnell und leicht zu erlernen sind.

Dies führt auch dazu, dass Entwickler sich daran gewöhnt haben, relational zu denken. Modelle werden lieber „platt geklopft“ als sie „anders“ abzubilden. Für viele Fälle ist das auch sicherlich der kostengünstigere Weg.

Dennoch lohnt sich gerade bei Graphen-Datenbanken der Blick über den Tellerrand. Vielleicht schaffen wir es ja, dieses Modell ebenso flexibel einzusetzen wie das der relationalen Datenbank.

Links: