Spring Data – Teil 5: Neo4j

9 Kommentare

Introduction

Neo4j [1] ist ein hochperformanter NoSQL [2] Datastore, der auf die Verarbeitung von Graphen spezialisiert ist. Ein Graph [3] ist eine Datenstruktur, die aus einer endlichen Menge von Knoten und Kanten besteht, wobei eine Kante eine Verbindung zwischen zwei Knoten ist. Graphen werden verwendet, um Beziehungen oder Verbindungen (Kanten) zwischen Domain-Objekten (Knoten) zu repräsentieren. Soziale Netzwerke stellen einen Anwendungsfall dieser Datenstruktur dar.

Neo4j

Nach dem Download der Community Edition von Neo4j [4] wird das ZIP in einen Ordner NEO4J_HOME entpackt und der Server mit

${NEO4J_HOME}/bin/Neo4J.bat

gestartet (auf einem Windows OS). Standardmäßig kann die Admin-Oberfläche unter http://localhost:7474/webadmin zugegriffen werden. Sie enthält u.a. eine Web-basierte Shell. Für den Anfang kann man mit den „Data browser“ manuell Knoten und Relationen einfügen und sich auch graphisch darstellen lassen.

Spring Data Neo4j

Zunächst lassen wir Maven die aktuelle Version von Spring Data Neo4j herunterladen:

<dependency>
   <groupId>org.springframework.data</groupId>
   <artifactId>spring-data-neo4j</artifactId>
   <version>2.0.0.RELEASE</version>
</dependency>

Da wir Neo4j per Remote REST Call zugreifen wollen, benötigen wir diese optionale Abhängigkeit:

<dependency>
   <groupId>org.springframework.data</groupId>
   <artifactId>spring-data-neo4j-rest</artifactId>
   <version>2.0.0.RELEASE</version>
</dependency>

Wie bei allen Spring Data Projekten ist die Konfiguration über spezielle XML Namensräume sehr einfach. Wir verwenden den Namensraum neo4j:

<!-- REST Connection to Neo4j server -->
<bean id="restGraphDatabase" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
  <constructor-arg value="http://localhost:7474/db/data/" />
</bean>
 
<!-- Neo4j configuration (creates Neo4jTemplate) -->
<neo4j:config graphDatabaseService="restGraphDatabase" />
 
<!-- Package w/ automagic repositories -->
<neo4j:repositories base-package="neo4j" />

Wir geben die Basis-URL für den REST-Zugriff an und verwenden diesen Service für die weitere Neo4j-Konfiguration.

Die grundsätzliche Idee hinter Spring Data ist, eigene Finder-Methode nur als Interface-Methode zu beschreiben. Spring stellt dann zur Laufzeit eine geeignete Implementierung samt aller gängigen CRUD-Operationen zur Verfügung. Um dies in einer Anwendung zu nutzen, muss noch das Paket mit diesen Interfaces über <neo4j:repositories ...> konfiguriert werden.

Domain Object

Wie in den vorangegangenen Beiträge in dieser Blog-Serie werden wir einige einfach User-Objekte abspeichern. Die Neo4j-Version davon kann so aussehen:

/** Simple user class. */
@NodeEntity public class User {
 
  @GraphId Long id;
 
  @Indexed private String login;
 
  private String fullName;
 
  private Date lastLogin;
 
  @RelatedTo(type = "knows", direction = Direction.OUTGOING)
  Set<User> friends;	
  ...

Um die Neo4j-Persistenz zu nutzen verwendet man die Annotation @NodeEntity auf Klassenebene. Die eindeutige Id eines Knoten wird mit @GraphId annotiert. Die Vergabe dieser Ids übernimmt Neo4j transparent. Such-Indexe können mit der @Indexed-Annotation definiert werden.

Ein Beziehung zwischen unseren Usern namens knows (die ausdrücken soll, dass ein User U einen anderen User V kennt) definieren wir mit der Annotation @RelatedTo an einem Set von Usern.

Das folgende Beispiel verwendet einen Graphen solcher User. Wir werden mit n Usern arbeiten. Jeder User U_i kennt alle anderen User U_j (für alle 0 <= i < j <= n). Ein User root kennt alle anderen User. Für n = 3 kann der Graph wie folgt ausssehen:

Zur Visualisierung von Neo4j-Graphen kann auch eine RCP-Anwendung namens Neoclipse [6] verwendet werden-

Repository

Zur Definition eines Repositories mit allen CRUD-Operationen genügt bereits eine einzige Codezeile:

public interface UserRepository extends GraphRepository<User> {}

Eigene Finder werden wir gleich hinzufügen. Nun werden wir erst mal einige User speichern mit der save()-Methode:

...
// build graph
for ( int i = 0; i < user.length; i++ ) {
  root.knows(user[i]);
  for ( int j = i; j < user.length; j++ ) {
    user[i].knows(user[j]);
  }
}
 
// save nodes
for ( int i = 0; i < user.length; i++ ) {
  repo.save(user[i]);
}
repo.save( root );

Zur besseren Lesbarkeit haben wir eine Methode knows(...) spendiert, die den übergebenen User der Menge der bekannten User hinzufügt. Kennt man die Id eines gespeicherten Knotens, kann man dessen Daten im Browser anzeigen lassen:

http://localhost:7474/db/data/node/98

Um über das Spring Data API einzelne Knoten zu laden, kann der Standard-Finder findOne(long) verwendet werden:

User root = repo.findOne(rootId);

Nun ergänzen wir unser Repository um einige eigene Finder-Methoden:

public interface UserRepository extends GraphRepository<User> {
 
  User findByLogin(String login);
 
  @Query("START root=node:User(login = 'root') MATCH root-[:knows]->friends RETURN friends")
  List<User> findFriendsOfRoot();
}

Die erste Query liefert einen einzelnen Knoten, dessen Property login mit dem Suchkriterium übereinstimmt. Mit Hilfe der Annotation @Query kann man auch frei definierbare Cypher [5] Queries schreiben. Dies übernimmt die zweite Query, die alle dem User root bekannten User liefert.

Der komplette Quellcode des Beispiel kann unter github heruntergeladen werden.

Zusammenfassung

Das war’s für heute. Ich habe gezeigt, wie man einen Neo4j-Server installiert und startet. Wir haben ein Maven-basiertes Spring Data Neo4j-Projekt angelegt und konfiguriert. Nach dem Speichern eines eigenen Graphen haben wir eigene Finder geschrieben und auch direkt die Cypher Query Langugage verwwendet.

Das war natürlich nur ein kleiner Einblick ins Universum von Neo4j. Ich hoffe, es hat Euch gefallen. Für einen vertiefenden Einstieg empfehle ich die Neo4j-Homepage. Dort werden Themen wie eingebettete Datenbank mit Transaktionsunterstützung und Geodaten-Suchen beschrieben.

Das Spring Data Projekt

Dies sind meine andere Posts zum Thema Spring Data:

Teil 3: Spring Data Mongo DB
Teil 2: Spring Data JPA
Teil 1: Spring Data Commons

References

[1] Neo4j
[2] NoSQL databases
[3] Graphs
[4] Neo4j Download
[5] Cypher Cookbook
[6] Neoclipse Download

Autor

Tobias Trelle

Tobias Trelle

Senior IT Consultant

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentare

  • Thank you

    I am begginer and i was trying understand Neo4j with spring data and you help me a lot!!!!

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *