22
.
1
.
2014

Ein Hands-On Rundgang durch Neo4j 2.0

Letzte Woche hat unser Partner Neo Technologies offiziell den neuen Release 2.0 der Graphdatenbank Neo4j herausgebracht. Auch bei comSysto setzen wir Neo4j ein und veranstalten regelmäßig Trainings. Das nächste Neo4j Training wird am 25. März stattfinden. Hier geht’s zur Anmeldung.

Wir nehmen den Release von Neo4j 2.0 zum Anlass, uns die neuen Features einmal genauer anzusehen.

Labels

Die wichtigste Neuerung bei Neo4j 2.0, von der man schon im Vorfeld viel hören konnte, sind Labels. Doch was bringen sie eigentlich? Im Prinzip ist ein Label nur eine spezielle Form von Property. Allerdings bringt Neo4j 2.0 darauf aufbauend eine Reihe weiterer Features mit, auf die ich im Folgenden genauer eingehen werde.

Die Cineasts Datenbank

Viele Leser werden die Cineasts-Datenbank von Neo4j kennen. Für alle anderen hier eine Skizze des für uns relevanten Schemas:

Beispieldaten Cineasts-DB
Beispieldaten Cineasts-DB

Im “Schema” gibt es Filme, die eingehende Relationen vom Typ DIRECTED und ACTS_IN haben. Alle Knoten, die mindestens eine ausgehende ACTS_IN Relation besitzen, sind Schauspieler. Die Knoten, die eine ausgehende DIRECTED Relation haben, sind Regisseure. Natürlich gibt es auch Schauspieler, die auch Regie geführt haben. Es gibt noch weitere Relationen und Knotentypen, auf die wir hier aber nicht weiter eingehen wollen.

Ihr findet das Schema zum Download bei Neo4j. Nach dem Download entpackt ihr das Zip-File, benennt den Ordner in cineasts.db um und verschiebt ihn in das Verzeichnis data der Neo4j-Installation:

github:1327990e3062bb5a3895

Anschließend muss der Pfad zur Cineasts-Datenbank unter conf/neo4j-server.propertieskonfiguriert werden

github:35aa887150528f774597

Da es sich um eine mit Neo4j 1.9 erzeugete Datenbank handelt, muss die Option allow_store_upgrade in conf/neo4j.properties aktiviert werden:

github:418cef9c756ea0d9139f

Damit sind wir bereit, den Server zu starten:

github:98159c5c00b40e436da4

Unter http://localhost:7474 findet sich bereits die erste Neuerung – das neue WebInterface:

Das Neo4j 2.0 WebInterface
Das Neo4j 2.0 WebInterface

Da wir uns später den Execution-Plan der Queries anschauen wollen, steigen wir gleich auf die Neo4j-Shell um. Diese könnt ihr mit ./bin/neo4j-shell starten.

Legen wir also richtig los und schauen uns zuerst einmal an, wie viele Schauspieler wir im Datenbestand haben:

github:040dde083bf215e1a515

Mit Version 2.0 gibt es auch einige Änderungen bei der Syntax der Abfragesprache Cypher. Eine davon ist, dass die START-Clause jetzt optional ist. Lassen wir sie also einfach weg:

github:7ea5d0f7e2d0464ea9ff

Labels erzeugen und Verwenden

Wie eingangs erwähnt, erkennen wir alle Schauspieler daran, dass sie in einem Film mitgespielt haben und somit über eine ausgehende ACTS_IN Relation verfügen. Die neue Möglichkeit, einen „Knotentypen“ explizit festzulegen, sind Labels. Also versehen wir einfach alle Schauspieler-Knoten mit einem Label „Actor“:

github:b77cbfa8bc558ff0aa3f

Um nun die Anzahl aller Schauspieler herauszufinden, können wir das Label benutzen:

github:fdf42a1d4ac093df5d09

Dabei fällt auf, dass die Query dieses mal fast um den Faktor 10 schneller ist als zuvor. Um herauszufinden, woran das liegt, führen wir beide Queries mit dem Keyword PROFILE aus:

github;bfe1b37606091fa7b72d

Wie man an der Anzahl an Datenbankzugriffen (den _db_hits) ablesen kann, wurde für das Ergebnis der zweiten Query kein Datenbankzugriff gebraucht. Die Anzahl der Knoten wurde mit Hilfe eines Index’ bestimmt, der alle Knoten mit einem Label indiziert. Natürlich war das auch vor Version 2.0 möglich, jedoch musste ein solcher Index programmatisch erzeugt werden. Jetzt genügt eine einfache Cypher-Query.

Legen wir nun zwei weitere Labels für Filme (“Movie”) und Regisseure (“Director”) an, dann sehen unsere Daten jetzt so aus:

Beispieldaten Cineasts-DB mit Labels
Beispieldaten Cineasts-DB mit Labels

Labels und Indexe

Eine weitere interessante Neuerung hatten wir eben schon kurz angerissen: Indexe, oder genauer gesagt: das Erzeugen von Indexen. Vor Version 2.0 konnte man Indexe programmatisch oder per REST-API anlegen oder den Auto-Index verwenden. Nun können Indexe einfach mit Cypher-Statements für bestimmte Labels erzeugt werden, also ohne den eigentlichen Programmcode anzufassen.

Das wollen wir auch gleich an einem einfachen Beispiel probieren. Wir suchen den Schauspieler mit dem Namen “Mel Gibson” und schauen uns mit PROFILE den Execution-Plan der Anfrage an. Die Cypher-Query sieht wie folgt aus:

github:4a9fd3a82a917d915113

Man kann am Execution-Plan ablesen, dass alle Nodes mit dem Label “Actor” aus dem Index gelesen werden. Neo4j iteriert über alle 44943 Knoten und liefert diejenigen zurück, welche eine Property “name” mit dem Wert “Mel Gibson” besitzen.Wir erstellen nun einen Index auf der Property “name” für Knoten mit dem Label “Actor”:

github:fa7d010a260671607af0

Anschließend führen wir dieselbe Query noch einmal aus und schauen uns den Execution-Plan an:

github:e07f74df8da3c2bcc68d

Man kann sehen, dass sich der Execution-Plan geändert hat: Bei “Actor”-Knoten wurde automatisch der neue Index für die “name”-Property verwendet, ohne dass sich die Query geändert hat. Es wurde in der gesamten Ausführung genau ein Knoten angefasst, da der Index einen Verweis auf den richtigen Knoten zurückgibt und von dort lediglich “name” ausgelesen werden muss. Die Ausführungszeit der Query hat sich von 93ms auf 15ms reduziert.

Hier sieht man die interessanten Features, die nun durch Labels möglich sind. Neo4j und Cypher machen damit relationalen Datenbanken und SQL echte Konkurrenz.

Es ist außerdem möglich, Constraints auf Basis von Labels zu definieren. Aktuell gibt es jedoch ausschließlich Unique-Constraints. Man muss bei allen Labels, Indexen und Constraints natürlich bedenken, dass man dadurch ein Schema definiert, wobei diese Art Schema sicher nicht so starr ist wie das Schema einer relationalen Datenbank.

Transactions als REST-Ressource

Das letzte neue Feature ,das wir uns noch betrachten wollen, sind REST-Transaktionen. Mit Neo4j 2.0 sind Transaktionen Ressourcen, die wenn nötig über HTTP an den Aufrufenden geschickt werden. Zum Testen der REST-Schnittstelle eignet sich das WebInterface hervorragend. Dazu startet man den Befehl mit einem Doppelpunkt und dem Namen der gewünschten HTTP-Methode, gefolgt von einer relativen URL und einem Request-Body. Wir werden uns das jetzt am Beispiel anschauen, indem wir in einer Transaktion den weltberühmten Schauspieler ‘Max Mustermann’ in per REST-API in unsere Datenbank aufnehmen:

github:1c24898a408b45c586ee

Da eine Transaktion erzeugt wurde, können wir davon ausgehen, dass auch der Schauspieler-Knoten von “Max Mustermann” angelegt wurde. Wir werden jetzt in einer neuen Transaktion nach “Max Mustermann” suchen, ohne die vorherige Transaktion zu committen:

github:208341e8d354eec00990

Das Array “data” ist leer, entsprechend wurde der Schauspieler “Max Mustermann” nicht gefunden. Committen wir jetzt die erste Transaktion und führen erneut die Suche nach “Max Mustermann” aus:

github:a3a591a26354e3baa7c3
 github:f3bfe20f5791218ed4e8

Und siehe da, der gesuchte Knoten wird zurückgeliefert. Wir sehen hier eine weitere Eigenschaft der transaktionalen REST-API: man kann eine Transaktion mit einem HTTP-Request erzeugen und committen. Das hat natürlich den Vorteil, dass weniger Netzwerk-Overhead entsteht.

Die Möglichkeit, mehrere Statements in eine Transaktion zu kapseln, hatte man vor Version 2.0 nur im Embedded-Mode oder im Server-Mode unter Verwendung von Plugins bzw. Unmanaged Extensions.

Fazit

Es gibt noch eine Reihe weiterer Neuerungen, wie zum Beispiel die Syntax-Verbesserungen für Cypher oder die `MERGE`-Operation, jedoch sind meiner Meinung nach Labels (und die damit verbundenen Features) und die transaktionale REST-API die Highlights von Neo4j 2.0 . Dadurch ist die Entwicklung von Anwendungen mit Neo4j wesentlich flexibler geworden. Es gibt kaum noch Use Cases, die nicht durch Cypher abgedeckt werden können, wodurch es – im Zusammenspiel mit der transaktionalen REST-API – wesentlich einfacher wird, zu skalieren und aus dem Embedded-Mode in den Server-Mode zu wechseln (vice versa). Man muss sich nicht schon zu Beginn der Entwicklung festlegen, sondern kann – ganz agil – auf eine veränderte Umgebung reagieren.

Neo4j Training

Neugierig geworden? Dann sichert Euch einen Platz beim nächsten Neo4j Training am 25.3.2014 in München. Wir freuen uns auf Euch!