Nodes with key-value properties are connected by typed, directed relationships with properties.
TODO put in a pretty picturestart movie=(id) match movie<-[:ACTS_IN]-actor where actor.age > 20 return movie, actor.name order by movie.title
TraversalDescription actors = Traversal.description()
.relationships("ACTS_IN").filter(returnAllButStartNode());
for (Node actor : actors.traverse(movie))
...
Transaction tx=graphDatabaseService.beginTx();
try {
... graph operations ...
tx.success();
} catch(Exception e) {
tx.failure();
} finally {
tx.finish();
}
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j[-aspects]</artifactId>
<version>2.0.0.RC1</version>
</dependency>
<beans ... xmlns:neo4j="http://www.swf.org/schema/data/neo4j" xsi:schemaLocation= "http://www.sfw.org/schema/data/neo4j" ...> ... <neo4j:config store-dir="graph.db"/> <neo4j:repositories base-package="com.example.repositories"/> ... </beans>
<neo4j:config graphDatabaseService="gds"/> <bean id="gds" class="...ImpermanentGraphDatabase"/>
<neo4j:config graphDatabaseService="rds"/> <bean id="rds" class="...SpringRestGraphDatabase"/>
@NodeEntity marks a domain class as backed by a node in the graph@RelationshipEntity marks a domain class as backed by a relationship in the graph@GraphId Field for id@Indexed([fulltext=true],[indexName=name]) Auto-Indexing@RelatedTo([direction=Direction], [type=TYPE]) define type and direction of relationship on Entity, Iterable<E>, Set<E> fields@RelatedToVia([direction=Direction], [type=TYPE]) like @RelatedTo, but targets Relationship-Entities@Query(query, [type=QueryType]) computed field, executes graph query in Cypher or Gremlin@GraphTraversal(traversal=~TraversalBuilder.class, [elementClass=Person.class]) computed field, executes traversal starting from entity-node
@NodeEntity
public class Movie {
@GraphId Long id;
@Indexed(fulltext = true, indexName = "search")
String title;
Person director;
@RelatedTo(type="ACTS_IN", direction = INCOMING)
Set<Person> actors;
@RelatedToVia(type = "RATED")
Iterable<Rating> ratings;
@Query("start movie=node({self}) match
movie-->genre<--similar return similar")
Iterable<Movie> similarMovies;
}
interface MovieRepository extends GraphRepository<Movie> {
@Query("start movie={0} match m<-[rating:RATED]-user
return rating")
Iterable<Rating> getRatings(Movie movie);
// Co-Actors
Iterable<Person> findByActorsMoviesActorName(name)
}
<neo4j:repositories base-package="com.example.dao"/>
getPersistentState() relateTo(target, ...), getRelationshipTo(...) persist(), remove(), detach() ...
roo> addon search graph roo> addon install id --searchResultId 01 roo> project --topLevelPackage net.cineasts roo> graph setup --provider NEO4J --databaseLocation cineasts roo> graph entity --class ~.model.Movie roo> field string title roo> graph entity --class ~.model.Actor roo> field string name roo> graph relationship --to Movie --from Actor --fieldName movies --type ACTS_IN --cardinality ONE_TO_MANY roo> controller all --package ~.web
org.neo4j:neo4j-rest-graphdb)