updated documentation, fixed page/sort-test asserts

This commit is contained in:
Michael Hunger
2011-06-27 16:23:56 +02:00
parent 75c62d5490
commit 0ac1bfc51a
5 changed files with 102 additions and 8 deletions

View File

@@ -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;
}

View File

@@ -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<Person> 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<Person> 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<Person> 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<Person> 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

View File

@@ -117,5 +117,12 @@ public void foo( @Context WorldRepository repo ) {
</example>
Your project is now set up to work against a remote Neo4j Server.
</para>
<para>
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. <code>queryEngineFor(), index() and createTraversalDescription()</code>).
Please use those methods when interacting with a remote server for optimal performance.
</para>
</section>
</chapter>

View File

@@ -113,6 +113,24 @@
<para><code>Iterable&lt;EntityPath> findAllPathsByTraversal(traversalDescription)</code></para>
</listitem>
</varlistentry>
<varlistentry>
<term>Executes the given query, replacing the first %d with the node-id and returning the results converted to the target type.</term>
<listitem>
<para><code>&lt;T&gt; Iterable&lt;T&gt; NodeBacked.findAllByQuery(final String query, final Class&lt;T&gt; targetType)</code></para>
</listitem>
</varlistentry>
<varlistentry>
<term>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.</term>
<listitem>
<para><code>Iterable&lt;Map&lt;String,Object&gt;&gt; NodeBacked.findAllByQuery(final String query)</code></para>
</listitem>
</varlistentry>
<varlistentry>
<term>Executes the given query, replacing the first %d with the node-id and returns a single result converted to the target type.</term>
<listitem>
<para><code>&lt;T&gt; T NodeBacked.findByQuery(final String query, final Class&lt;T&gt; targetType)</code></para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>

View File

@@ -19,6 +19,10 @@
<!--<code>@Query(query="{name:%s}") findByName(name)</code>)-->
<!--</para>-->
<!--</note>-->
<para>
Spring Data Graph repositories support annotated and named queries for the Neo4j
<ulink url="http://docs.neo4j.org/chunked/milestone/query-lang.html">Cypher</ulink> query-language.
</para>
<para>
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 @@
</para>
</section>
<section>
<title>Cypher-Queries</title>
<section>
<title>Annotated Queries</title>
<para>
Queries for the graph-query language cypher can be supplied with the <code>@GraphQuery</code> annotation.
That means every method annotated with <code>@GraphQuery("start n=(%d) match (n)-->(m) return m")</code>
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 <code>Sort</code> and <code>Pageable</code>
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).
</para>
</section>
<section>
<title>Named Queries</title>
<para>Spring Data Graph also supports the notion of named queries which are externalized in property-config-files
(<code>META-INF/graph-named-queries.properties</code>). Those files have the format:
<code>Entity.finderName=query</code> (e.g. <code>Person.findBoss=start p=(%d) match (p)&lt;-[:BOSS]-(boss) return boss</code>).
Otherwise named queries support the same parameters as annotated queries.
</para>
</section>
<section>
<title>Query results</title>
<para>Typical results for queries are <code>Iterable&lt;Type&gt;, Iterable&lt;Map&lt;String,Object&gt;&gt;, Type and Page&lt;Type&gt;</code>.
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).
</para>
</section>
<section>
<title>Cypher Examples</title>
<para>There is a <ulink url="http://neo4j.vidcaster.com/U2Y/introduction-to-cypher">screencast</ulink> available showing many features of the query language.
The following examples are taken from the cineasts dataset of the tutorial section.
<variablelist>
<varlistentry>
<term><code>start n=(0) return n</code></term>
<listitem><para>returns the node with id 0</para></listitem>
</varlistentry>
<varlistentry>
<term><code>start movie=(Movie,title,'Matrix') return movie</code></term>
<listitem><para>returns the nodes which are indexed as 'Matrix'</para></listitem>
</varlistentry>
<varlistentry>
<term><code>start movie=(Movie,title,'Matrix') match (movie)&lt;-[:ACTS_IN]-(actor) return actor.name</code></term>
<listitem><para>returns the names of the actors that have a ACTS_IN relationship to the movie node for matrix</para></listitem>
</varlistentry>
<varlistentry>
<term><code>start movie=(Movie,title,'Matrix') match (movie)&lt;-[r,:RATED]-(user) where r.stars > 3 return user.name, r.stars, r.comment</code></term>
<listitem><para>returns users names and their ratings (>3) of the movie matrix</para></listitem>
</varlistentry>
<varlistentry>
<term><code>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</code></term>
<listitem><para>returns the movies rate by the friends of the user 'micha', aggregated by movie.title, with averaged ratings and rating-counts sorted by both</para></listitem>
</varlistentry>
</variablelist>
</para>
</section>
</section>
<section>
<title>Creating repositories</title>
<para>