Documentation Updates (Template, Gremlin)
This commit is contained in:
@@ -2,6 +2,17 @@
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
||||
<book xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<!-- TODO
|
||||
* Gremlin @Query on fields
|
||||
* Gremlin @Query on repository methods
|
||||
* variables in gremlin queries
|
||||
* variables in cypher queries
|
||||
* New Template Query API
|
||||
* Spring Roo Addon, Intro, Example Session
|
||||
* Update tutorial to include some of the new features (cypher, gremlin)
|
||||
*
|
||||
* more on Gremlin / Cypher over REST
|
||||
-->
|
||||
<bookinfo>
|
||||
<title>Good Relationships</title>
|
||||
<subtitle>The Spring Data Graph Guide Book</subtitle>
|
||||
@@ -23,14 +34,6 @@
|
||||
<firstname>David</firstname>
|
||||
<surname>Montag</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Mark</firstname>
|
||||
<surname>Pollack</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Thomas</firstname>
|
||||
<surname>Risberg</surname>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<legalnotice>
|
||||
@@ -40,6 +43,9 @@
|
||||
further provided that each copy contains this Copyright Notice, whether
|
||||
distributed in print or electronically.
|
||||
</para>
|
||||
<para>
|
||||
Copyright 2010-2011 Neo Technology
|
||||
</para>
|
||||
</legalnotice>
|
||||
|
||||
</bookinfo>
|
||||
|
||||
@@ -3,44 +3,76 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
||||
<preface>
|
||||
<title>About this guide book</title>
|
||||
<para>
|
||||
Welcome to the Spring Data Graph Guide Book. Thank you for taking the time to get an in depth look
|
||||
into <ulink url="https://github.com/SpringSource/spring-data-graph">Spring Data Graph</ulink>.
|
||||
This project is part of the <ulink url="http://springsource.org/spring-data">Spring Data project</ulink>,
|
||||
which brings the convenient programming model of the Spring Framework to modern NOSQL databases.
|
||||
Spring Data Graph, as the name alludes to, aims to provide support for graph databases. It currently
|
||||
supports <ulink url="http://neo4j.org">Neo4j</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
It was written by developers for developers. Hopefully we've created a document that is well received
|
||||
by our peers.
|
||||
</para>
|
||||
<para>
|
||||
If you have any feedback on Spring Data Graph or this book, please provide it via the
|
||||
<ulink url="https://jira.springsource.org/browse/DATAGRAPH">SpringSource JIRA</ulink>, the
|
||||
<ulink url="http://forum.springsource.org/forumdisplay.php?f=80">SpringSource NOSQL Forum</ulink>,
|
||||
<ulink url="https://github.com/SpringSource/spring-data-graph/issues">github comments or issues</ulink>,
|
||||
or the <ulink url="http://neo4j.org/community/list/">Neo4j mailing list</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
This book is presented as a <ulink url="http://martinfowler.com/bliki/DuplexBook.html">duplex book</ulink>,
|
||||
a term coined by Martin Fowler. A duplex book consists of at least two parts. The first part is an easily
|
||||
accessible tutorial that gives the reader an overview of the topics contained in the book. It contains lots
|
||||
of examples and discussion topics. This part of the book is highly suited for cover-to-cover reading.
|
||||
</para>
|
||||
<para>
|
||||
We chose a tutorial describing the creation of a web application that allows movie enthusiasts to
|
||||
find their favorite movies, rate them, connect with fellow movie geeks, and enjoy social features such as
|
||||
recommendations. The application is running on Neo4j using Spring Data Graph and the well-known Spring
|
||||
Web Stack.
|
||||
</para>
|
||||
<para>
|
||||
The second part of the book is the classic reference documentation, containing detailed information about
|
||||
the library. It discusses the programming model, the underlying assumptions, and internals, as well as the
|
||||
APIs for the object-graph mapping. The reference documentation is typically used to look up concrete bits of
|
||||
information, or to drill down into certain topics. For hackers wanting to really delve into Spring Data
|
||||
Graph, it can of course also be read cover-to-cover.
|
||||
</para>
|
||||
<section>
|
||||
<title>The Spring Data Graph Project</title>
|
||||
<para>
|
||||
Welcome to the Spring Data Graph Guide Book. Thank you for taking the time to get an in depth look
|
||||
into <ulink url="https://github.com/SpringSource/spring-data-graph">Spring Data Graph</ulink>.
|
||||
This project is part of the <ulink url="http://springsource.org/spring-data">Spring Data project</ulink>,
|
||||
which brings the convenient programming model of the Spring Framework to modern NOSQL databases.
|
||||
Spring Data Graph, as the name alludes to, aims to provide support for graph databases. It currently
|
||||
supports <ulink url="http://neo4j.org">Neo4j</ulink>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Feedback</title>
|
||||
<para>
|
||||
It was written by developers for developers. Hopefully we've created a guide that is well received
|
||||
by our peers.
|
||||
</para>
|
||||
<para>
|
||||
If you have any feedback on Spring Data Graph or this book, please provide it via the
|
||||
<ulink url="https://jira.springsource.org/browse/DATAGRAPH">SpringSource JIRA</ulink>, the
|
||||
<ulink url="http://forum.springsource.org/forumdisplay.php?f=80">SpringSource NOSQL Forum</ulink>,
|
||||
<ulink url="https://github.com/SpringSource/spring-data-graph/issues">github comments or issues</ulink>,
|
||||
or the <ulink url="http://neo4j.org/community/list/">Neo4j mailing list</ulink>.
|
||||
</para>
|
||||
</section>
|
||||
<section><title>Format of the Book</title>
|
||||
<para>
|
||||
This book is presented as a <ulink url="http://martinfowler.com/bliki/DuplexBook.html">duplex book</ulink>,
|
||||
a term coined by Martin Fowler. A duplex book consists of at least two parts. The first part is an easily
|
||||
accessible tutorial that gives the reader an overview of the topics contained in the book. It contains lots
|
||||
of examples and discussion topics. This part of the book is highly suited for cover-to-cover reading.
|
||||
</para>
|
||||
<para>
|
||||
We chose a tutorial describing the creation of a web application that allows movie enthusiasts to
|
||||
find their favorite movies, rate them, connect with fellow movie geeks, and enjoy social features such as
|
||||
recommendations. The application is running on Neo4j using Spring Data Graph and the well-known Spring
|
||||
Web Stack.
|
||||
</para>
|
||||
<para>
|
||||
The second part of the book is the classic reference documentation, containing detailed information about
|
||||
the library. It discusses the programming model, the underlying assumptions, and internals, as well as the
|
||||
APIs for the object-graph mapping. The reference documentation is typically used to look up concrete bits of
|
||||
information, or to drill down into certain topics. For hackers wanting to really delve into Spring Data
|
||||
Graph, it can of course also be read cover-to-cover.
|
||||
</para>
|
||||
</section>
|
||||
<section><title>Acknowledgements</title>
|
||||
<para>
|
||||
We would like to thank everyone who contributed to this book, especially Mark Pollack and Thomas Risberg,
|
||||
the leads of the Spring Data Project, who helped a lot during the development of the library as well as sharing
|
||||
great feedback about the book. Also Oliver Gierke, our local German VMWare/SpringSource engineer, who invested a
|
||||
lot of time discussing various aspects of the library as well as providing the superb foundations for the Spring
|
||||
Data Repositories. We tortured Andy Clement, the AspectJ project lead, with many questions and issues around our
|
||||
advanced AspectJ usage which caused some headaches. He always quickly solved our issues and gave us excellent
|
||||
answers.
|
||||
</para>
|
||||
<para>
|
||||
We also appreciate very much the foresight of Rod Johnson and Emil Eifrem to initiate the project, and now
|
||||
also providing great forewords. Their leadership inspired collaboration between the engineering teams at
|
||||
SpringSource and Neo Technology, a tremendous help during the making of Spring Data Graph.
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Last but not least we thank our vibrant community, both in the Spring Forums as well as on the Neo4j
|
||||
Mailing list and on many other places on the internet for giving us feedback, reporting issues and suggesting
|
||||
improvements. Without that important feedback we wouldn't be where we are today.
|
||||
|
||||
</para>
|
||||
</section>
|
||||
<para>
|
||||
Enjoy the book!
|
||||
</para>
|
||||
|
||||
@@ -88,8 +88,8 @@ public void foo( @Context WorldRepository repo ) {
|
||||
</note>
|
||||
<para>
|
||||
Please also keep in mind that performing graph operations via the REST-API is about one order of
|
||||
magnitude slower than location operations. Try to use the Neo4j-Query-Language or
|
||||
server-side traversals whenever possible (<code>RestTraversal</code>) for retrieving large sets of data.
|
||||
magnitude slower than location operations. Try to use the Neo4j Cypher query language,
|
||||
server-side traversals (<code>RestTraversal</code>) or Gremlin expressions whenever possible for retrieving large sets of data.
|
||||
Future versions of Spring Data Graph will use the more performant batching as well as a binary protocol.
|
||||
</para>
|
||||
<para>
|
||||
@@ -124,5 +124,8 @@ public void foo( @Context WorldRepository repo ) {
|
||||
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>
|
||||
<para>
|
||||
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
@@ -150,6 +150,91 @@ try {
|
||||
for (Node foundNode : nodeIndex.get("property","value")) {
|
||||
// found node
|
||||
}
|
||||
]]></programlisting>
|
||||
</example>
|
||||
</section>
|
||||
<section>
|
||||
<title>Querying with Cypher</title>
|
||||
<para>
|
||||
With version 1.4.M04 Neo4j introduced a textual query language called
|
||||
<ulink url="http://docs.neo4j.org/chunked/milestone/cypher-query-lang.html">"Cypher"</ulink> which draws from many
|
||||
sources. From graph matching like in SPARQL, some keywords and query structure that reminds of SQL and
|
||||
some iconic representation. A screencast presenting cypher queries on the cineasts.net dataset is available
|
||||
at <ulink url="http://video.neo4j.org/U2Y/introduction-to-cypher">video.neo4j.org</ulink>. Cypher was written
|
||||
in Scala to leverage the high expressiveness for lazy sequence operations of the language and the great
|
||||
parser combinator library.
|
||||
</para>
|
||||
<para>
|
||||
Cypher queries always begin with a <code>start</code> set of nodes. Those can be either expressed by their
|
||||
id's or by a index lookup expression. Those start-nodes are then related to other nodes in the
|
||||
<code>match</code> clause to other nodes. Start and match clause can introduce new identifiers for nodes and
|
||||
relationships. In the <code>where</code> clause additional filtering of the result set is applied by evaluating
|
||||
boolean expressions. The <code>return</code> clause defines which part of the query result will be available.
|
||||
Aggregation also happens in the return clause by using aggregation functions on some of the values.
|
||||
Sorting can happen in the <code>order by</code> clause and the <code>skip</code> and <code>limit</code> parts
|
||||
restrict the result set to a certain window.
|
||||
</para>
|
||||
<para>
|
||||
Cypher can be executed on an embedded graph db using <code>ExecutionEngine</code> and
|
||||
<code>CypherParser</code>. This is encapsulated in Spring Data Graph with
|
||||
<code>CypherQueryEngine</code>. The Neo4j-REST-Server comes with a Cypher-Plugin that is accessible remotely and is
|
||||
available in the Spring Data Graph REST-Binding.
|
||||
</para>
|
||||
<example>
|
||||
<title>Cypher Examples on the Cineasts.net Dataset</title>
|
||||
<programlisting><![CDATA[
|
||||
// Actors of Forrest Gump:
|
||||
start movie=(Movie,id,'13') match (movie)<-[:ACTS_IN]-(actor)
|
||||
return actor.name, actor.birthplace?
|
||||
|
||||
// User-Ratings:
|
||||
start user=(User,login,'micha') match (user)-[r,:RATED]->(movie) where r.stars > 3
|
||||
return movie.title, r.stars, r.comment
|
||||
|
||||
// Mutual Friend recommendations:
|
||||
start user=(User,login,'micha') match (user)-[:FRIEND]-(friend)-[r,:RATED]->(movie) where r.stars > 3
|
||||
return friend.name, movie.title, r.stars, r.comment?
|
||||
|
||||
// Movie suggestions based on a movie:
|
||||
start movie=(Movie,id,'13') match (movie)<-[:ACTS_IN]-()-[:ACTS_IN]->(suggestion)
|
||||
return suggestion.title, count(*) order by count(*) desc limit 5
|
||||
|
||||
// Co-Actors, sorted by count and name of Lucy Liu
|
||||
start lucy=(1000) match (lucy)-[:ACTS_IN]->(movie)<-[:ACTS_IN]-(co_actor)
|
||||
return count(*), co_actor.name order by count(*) desc,co_actor.name limit 20
|
||||
|
||||
// recommendations including counts, grouping and sorting
|
||||
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
|
||||
]]></programlisting>
|
||||
</example>
|
||||
</section>
|
||||
<section>
|
||||
<title>Gremlin a Graph Traversal DSL</title>
|
||||
<para>
|
||||
Gremlin is an expressive Groovy DSL developed by <ulink url="http://markorodriguez.com">Marko Rodriguez</ulink>
|
||||
as part of the <ulink url="http://tinkerpop.com">tinkerpop</ulink> stack. It builds on top of a pipe implementation
|
||||
(Blueprints Pipes) that uses connected operations to traverse a graph. Gremlin has a concise syntax but is
|
||||
turing complete.
|
||||
</para>
|
||||
<para>Gremlin can be executed by including the tinkerpop and blueprints dependencies and then requesting a <code>ScriptEngine</code>
|
||||
of type "gremlin" from the <code>javax.Script*</code> facilities. In Spring Data Graph this is encapsulated in
|
||||
<code>GremlinQueryEngine</code>. The Neo4j-REST-Server also comes with a Gremlin-Plugin that is accessible remotely and is
|
||||
available in the Spring Data Graph REST-Binding.
|
||||
</para>
|
||||
<example>
|
||||
<title>Sample Gremlin Queries</title>
|
||||
<programlisting><![CDATA[
|
||||
// Vertex with id 1
|
||||
v = g.v(1)
|
||||
|
||||
// determine the name of the vertices that vertex 1 knows and that are older than 30 years of age
|
||||
v.outE{it.label=='knows'}.inV{it.age > 30}.name
|
||||
|
||||
// calculate basic collaborative filtering for vertex 1
|
||||
m = [:]
|
||||
g.v(1).out('likes').in('likes').out('likes').groupCount(m)
|
||||
m.sort{a,b -> a.value <=> b.value}
|
||||
]]></programlisting>
|
||||
</example>
|
||||
</section>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</note>
|
||||
<para>
|
||||
The AspectJ support in IntelliJ IDEA lacks some of the features. JetBrains is working on improving
|
||||
the situation in their upcoming 10.5 release of their popular IDE. Their latest work is available
|
||||
the situation in their upcoming 11 release of their popular IDE. Their latest work is available
|
||||
under their early access program (EAP). Building the project with the AspectJ compiler
|
||||
<code>ajc</code> works in IDEA (Options -> Compiler -> Java Compiler should show ajc). Make sure to
|
||||
give the compiler at least 512 MB of RAM.
|
||||
|
||||
@@ -14,68 +14,89 @@
|
||||
</para>
|
||||
<para>
|
||||
There are methods (<code>createNode()</code> and <code>createRelationship()</code>) for creating nodes and
|
||||
relationships that automatically set provided properties and optionally index certain fields.
|
||||
relationships that automatically set provided properties.
|
||||
</para>
|
||||
<example>
|
||||
<title>Neo4j template</title>
|
||||
<programlisting language="java"><![CDATA[<![CDATA[import static org.springframework.data.neo4j.core.Property._;
|
||||
<programlisting language="java"><![CDATA[<![CDATA[import static org.neo4j.helpers.collection.MapUtil.map;
|
||||
|
||||
Neo4jOperations neo = new Neo4jTemplate(graphDatabaseService);
|
||||
|
||||
Node michael = neo.createNode(_("name","Michael"));
|
||||
Node mark = neo.createNode(_("name","Mark"));
|
||||
Node thomas = neo.createNode(_("name","Thomas"));
|
||||
Node michael = neo.createNode(map("name","Michael"));
|
||||
Node mark = neo.createNode(map("name","Mark"));
|
||||
Node thomas = neo.createNode(map("name","Thomas"));
|
||||
|
||||
neo.createRelationship(mark,thomas, WORKS_WITH, _("project","spring-data"));
|
||||
neo.createRelationship(mark,thomas, WORKS_WITH, map("project","spring-data"));
|
||||
|
||||
neo.index("devs",thomas, "name","Thomas");
|
||||
|
||||
assert "Mark".equals(neo.query("devs","name","Mark",new NodeNamePathMapper()));
|
||||
]]></programlisting>
|
||||
// Cypher
|
||||
assert "Mark".equals(neo.query("start p=(%person) match p<-[:WORKS_WITH]-other return other.name",
|
||||
map("person",thomas)).to(String.class).single());
|
||||
|
||||
// Gremlin
|
||||
assert thomas.equals(neo.execute("g.v(person).out('WORKS_WITH')",
|
||||
map("person",mark)).to(Node.class).single());
|
||||
|
||||
// Index lookup
|
||||
assert mark.equals(neo.lookup("devs","name","Mark").single());
|
||||
|
||||
// Index lookup with Result Converter
|
||||
assert "Mark".equals(neo.lookup("devs","name","Mark").to(String.class, new ResultConverter<PropertyContainer, String> {
|
||||
public String convert(PropertyContainer element, Class<String> type) {
|
||||
return (String) element.getProperty("name");
|
||||
}}));]]></programlisting>
|
||||
</example>
|
||||
</section>
|
||||
<section>
|
||||
<title>QueryResult</title>
|
||||
<para>
|
||||
All querying methods of the template return a uniform result type: <code>QueryResult<T></code>
|
||||
which is also an <code>Iterable<T></code>. The query result offers methods of converting each
|
||||
element to a target type <code>queryResult.to(Type.class)</code> optionally supplying a
|
||||
<code>ResultConverter<FROM,TO></code> which takes care of custom conversions. By default most
|
||||
query methods can already handle conversions from and to: Paths, Nodes, Relationship and GraphEntities
|
||||
as well as conversions backed by registered ConversionServices. A converted <code>QueryResult<FROM></code> is an
|
||||
<code>Iterable<TO></code>. QueryResults can be limited to a single value using the <code>queryResult.single()</code>
|
||||
method. It also offers support for a pure callback function using a <code>Handler<T></code>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Indexing</title>
|
||||
<para>
|
||||
Adding nodes and relationships to an index is done with the <code>index()</code> method.
|
||||
</para>
|
||||
<para>
|
||||
The <code>query()</code> methods either take a field/value combination to look for exact matches in the
|
||||
index, or a Lucene query object or string to handle more complex queries. All <code>query()</code>
|
||||
methods provide <code>Path</code> results to a PathMapper.
|
||||
The <code>lookup()</code> methods either take a field/value combination to look for exact matches in the
|
||||
index, or a Lucene query object or string to handle more complex queries. All <code>lookup()</code>
|
||||
methods return a <code>QueryResult<PropertyContainer></code> to be used or transformed.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Graph traversal</title>
|
||||
<para>
|
||||
The traversal methods are at the core of graph operations. As such, they are fully supported in the
|
||||
<code>Neo4jTemplate</code>. The <code>traverseNext()</code> method traverses to the direct neighbors
|
||||
of the start node, filtering the relationships according to the parameters.
|
||||
</para>
|
||||
<para>
|
||||
The traversal methods are at the core of graph operations.
|
||||
The <code>traverse()</code> method covers the full traversal operation that takes a
|
||||
<code>TraversalDescription</code> (typically built with the <code>Traversal.description()</code>
|
||||
DSL) and runs it from the start node. Each path that is returned by the traversal is passed to the
|
||||
<code>PathMapper</code> to be converted into the desired type.
|
||||
DSL) and runs it from the given start node. <code>traverse</code> returns a <code>QueryResult<Path></code>
|
||||
to be used or transformed.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Path abstraction and PathMapper</title>
|
||||
<title>Cypher Queries</title>
|
||||
<para>
|
||||
For the querying operations Neo4jTemplate unifies the result with the <code>Path</code> abstraction that
|
||||
comes from Neo4j. Much like a result set, a path contains a chain of <code>nodes()</code> connected by
|
||||
<code>relationships()</code>, starting at a <code>startNode()</code> and ending at a
|
||||
<code>endNode()</code>. The <code>lastRelationship()</code> is also available separately. The
|
||||
<code>Path</code> abstraction also wraps results that contain just nodes or relationships.
|
||||
The <code>Neo4jTemplate</code> also allows execution of arbitrary Cypher queries. Via the <code>query</code>
|
||||
methods the statement and parameter-Map are provided. Cypher Queries return tabular results, so the
|
||||
<code>QueryResult<Map<String,Object>></code> contains the rows which can be either used as they are
|
||||
or converted as needed.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Gremlin Scripts</title>
|
||||
<para>
|
||||
Using implementations of <code>PathMapper<T></code> and <code>PathMapper.WithoutResult</code>
|
||||
(comparable with <code>RowMapper</code> and <code>RowCallbackHandler</code>), the paths can be converted
|
||||
to arbitrary Java objects.
|
||||
</para>
|
||||
<para>
|
||||
With <code>EntityPath</code> and <code>EntityMapper</code> there is also support for using
|
||||
node entities within the <code>Path</code> and <code>PathMapper</code> constructs.
|
||||
Gremlin Scripts can run with the <code>execute</code> method, which also takes the parameters that will be
|
||||
available as variables inside the script. The result of the executions is a generic
|
||||
<code>QueryResult<Object></code> fit for conversion or usage.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@@ -88,4 +109,11 @@ assert "Mark".equals(neo.query("devs","name","Mark",new NodeNamePathMapper()));
|
||||
or the <code>TransactionTemplate</code>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Neo4j REST Server</title>
|
||||
<para>If the template is configured to use a <code>RestGraphDatabase</code> the expensive operations
|
||||
like traversals and querying are executed efficiently on the server side by using the REST API to forward
|
||||
those calls. All the other template methods require single network operations.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user