From 0ac1bfc51a6fa591c5ea74936a96a19f8d8303b4 Mon Sep 17 00:00:00 2001 From: Michael Hunger Date: Mon, 27 Jun 2011 16:23:56 +0200 Subject: [PATCH] updated documentation, fixed page/sort-test asserts --- .../repository/GraphRepositoryFactory.java | 6 +- .../neo4j/support/GraphRepositoryTest.java | 15 +++-- src/docbkx/reference/neo4j-server.xml | 7 ++ .../programming-model/introducedmethods.xml | 18 ++++++ .../programming-model/repositories.xml | 64 +++++++++++++++++++ 5 files changed, 102 insertions(+), 8 deletions(-) diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/repository/GraphRepositoryFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/repository/GraphRepositoryFactory.java index 263828ba1..df0dba5ad 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/repository/GraphRepositoryFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/repository/GraphRepositoryFactory.java @@ -157,8 +157,10 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { } if (parameters.hasPageableParameter()) { final Pageable pageable = getPageable(args); - baseQuery = addSorting(baseQuery, pageable.getSort()); - baseQuery = addPaging(baseQuery, pageable); + if (pageable!=null) { + baseQuery = addSorting(baseQuery, pageable.getSort()); + baseQuery = addPaging(baseQuery, pageable); + } } return baseQuery; } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/GraphRepositoryTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/GraphRepositoryTest.java index 7f43cc850..3a72dc83b 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/GraphRepositoryTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/GraphRepositoryTest.java @@ -34,12 +34,15 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.BeforeTransaction; import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; +import java.util.List; import java.util.Map; import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; +import static org.junit.internal.matchers.IsCollectionContaining.hasItem; import static org.junit.internal.matchers.IsCollectionContaining.hasItems; import static org.neo4j.helpers.collection.IteratorUtil.asCollection; @@ -92,23 +95,23 @@ public class GraphRepositoryTest { public void testFindPaged() { final PageRequest page = new PageRequest(0, 1, Sort.Direction.ASC, "member.name"); Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(page, testTeam.sdg); - assertThat(teamMemberPage1, is((Iterable) asList(testTeam.david))); + assertThat(teamMemberPage1, hasItem(testTeam.david)); } @Test @Transactional public void testFindPagedDescending() { final PageRequest page = new PageRequest(0, 2, Sort.Direction.DESC, "member.name"); Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(page, testTeam.sdg); - assertThat(teamMemberPage1, is((Iterable) asList(testTeam.michael, testTeam.emil))); + assertEquals(asList(testTeam.michael, testTeam.emil), asCollection(teamMemberPage1)); assertThat(teamMemberPage1.isFirstPage(), is(true)); } @Test @Transactional public void testFindPagedNull() { Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(null, testTeam.sdg); - assertThat(teamMemberPage1, is((Iterable) asList(testTeam.michael, testTeam.emil))); + assertEquals(asList(testTeam.michael, testTeam.emil,testTeam.david), asCollection(teamMemberPage1)); assertThat(teamMemberPage1.isFirstPage(), is(true)); - assertThat(teamMemberPage1.isLastPage(), is(true)); + assertThat(teamMemberPage1.isLastPage(), is(false)); } @Test @@ -116,7 +119,7 @@ public class GraphRepositoryTest { public void testFindSortedDescending() { final Sort sort = new Sort(Sort.Direction.DESC, "member.name"); Iterable teamMembers = personRepository.findAllTeamMembersSorted(testTeam.sdg, sort); - assertThat(teamMembers, is((Iterable)asList(testTeam.michael, testTeam.emil, testTeam.david))); + assertEquals(asList(testTeam.michael, testTeam.emil, testTeam.david), asCollection(teamMembers)); } @Test diff --git a/src/docbkx/reference/neo4j-server.xml b/src/docbkx/reference/neo4j-server.xml index b08d2a959..60a58ae0d 100644 --- a/src/docbkx/reference/neo4j-server.xml +++ b/src/docbkx/reference/neo4j-server.xml @@ -117,5 +117,12 @@ public void foo( @Context WorldRepository repo ) { Your project is now set up to work against a remote Neo4j Server. + + The remote REST implementation works for both the Neo4jTemplate as well as the GraphEntities. For traversals + and cypher-graph-queries it is sensible to forward those to the remote and execute them there instead of + walking the graph over the wire. RestGraphDatabase already supports that by providing methods that forward + to the remote instance. (e.g. queryEngineFor(), index() and createTraversalDescription()). + Please use those methods when interacting with a remote server for optimal performance. + diff --git a/src/docbkx/reference/programming-model/introducedmethods.xml b/src/docbkx/reference/programming-model/introducedmethods.xml index 84c061455..a212334e2 100644 --- a/src/docbkx/reference/programming-model/introducedmethods.xml +++ b/src/docbkx/reference/programming-model/introducedmethods.xml @@ -113,6 +113,24 @@ Iterable<EntityPath> findAllPathsByTraversal(traversalDescription) + + Executes the given query, replacing the first %d with the node-id and returning the results converted to the target type. + + <T> Iterable<T> NodeBacked.findAllByQuery(final String query, final Class<T> targetType) + + + + Executes the given query, replacing the first %d with the node-id and returning the original result, but with nodes and relationships replaced by their appropriate entities. + + Iterable<Map<String,Object>> NodeBacked.findAllByQuery(final String query) + + + + Executes the given query, replacing the first %d with the node-id and returns a single result converted to the target type. + + <T> T NodeBacked.findByQuery(final String query, final Class<T> targetType) + + diff --git a/src/docbkx/reference/programming-model/repositories.xml b/src/docbkx/reference/programming-model/repositories.xml index 53b2c55c0..7a52a30bf 100644 --- a/src/docbkx/reference/programming-model/repositories.xml +++ b/src/docbkx/reference/programming-model/repositories.xml @@ -19,6 +19,10 @@ + + Spring Data Graph repositories support annotated and named queries for the Neo4j + Cypher query-language. + Spring Data Graph comes with typed repository implementations that provide methods for locating node and relationship entities. There are 3 types of basic repository interfaces @@ -123,6 +127,66 @@ +
+ Cypher-Queries +
+ Annotated Queries + + Queries for the graph-query language cypher can be supplied with the @GraphQuery annotation. + That means every method annotated with @GraphQuery("start n=(%d) match (n)-->(m) return m") + will use the query string. The String-format parameters are replaced by the actual method parameters in order, + whereby Node and Relationship-Entities are resolved to their respective id's and all other parameters are + replaced directly (i.e. Strings, Longs, etc). There is special support for the Sort and Pageable + parameters from Spring Data Commons, which are supported to add programmatic paging and sorting (alternatively + static paging and sorting can be supplied in the query string itself). + +
+ +
+ Named Queries + Spring Data Graph also supports the notion of named queries which are externalized in property-config-files + (META-INF/graph-named-queries.properties). Those files have the format: + Entity.finderName=query (e.g. Person.findBoss=start p=(%d) match (p)<-[:BOSS]-(boss) return boss). + Otherwise named queries support the same parameters as annotated queries. + +
+
+ Query results + Typical results for queries are Iterable<Type>, Iterable<Map<String,Object>>, Type and Page<Type>. + Nodes and Relationships are converted to their respective Entities (if they exist). Other values are converted + using the registered Spring conversion services (e.g. enums). + +
+
+ Cypher Examples + There is a screencast available showing many features of the query language. + The following examples are taken from the cineasts dataset of the tutorial section. + + + start n=(0) return n + returns the node with id 0 + + + start movie=(Movie,title,'Matrix') return movie + returns the nodes which are indexed as 'Matrix' + + + start movie=(Movie,title,'Matrix') match (movie)<-[:ACTS_IN]-(actor) return actor.name + returns the names of the actors that have a ACTS_IN relationship to the movie node for matrix + + + start movie=(Movie,title,'Matrix') match (movie)<-[r,:RATED]-(user) where r.stars > 3 return user.name, r.stars, r.comment + returns users names and their ratings (>3) of the movie matrix + + + start user=(User,login,'micha') match (user)-[:FRIEND]-(friend)-[r,:RATED]->(movie) return movie.title, AVG(r.stars), count(*) order by AVG(r.stars) desc, count(*) desc + returns the movies rate by the friends of the user 'micha', aggregated by movie.title, with averaged ratings and rating-counts sorted by both + + + +
+
+
Creating repositories