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)) ...
try (Transaction tx=graphDatabaseService.beginTx()) { ... graph operations ... tx.success(); } catch(Exception e) { tx.failure(); }
<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@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
)