updated documentation for server and indexing

This commit is contained in:
Michael Hunger
2011-03-27 03:48:28 +02:00
parent 3aa54a4832
commit 69690d3919
2 changed files with 163 additions and 25 deletions

View File

@@ -3,6 +3,77 @@
<chapter id="reference_neo4j-server">
<title>Neo4j Server</title>
<para>
...
Neo4j is not only available in embedded mode, it can also be installed and run as a server that is accessed
via a REST API. Spring Data Graph provides two-fold integration for infrastructure.
</para>
<section>
<title>Server Extension</title>
<para>
What is the use-case for writing server extensions? The REST API is a pretty generic representation of the
Neo4j core API. It is nice for getting started and simple scenarios. For more involved solutions that require
high speed and high volume access to the embedded graph database, writing a server extension that is able to
process external parameters and return just the relevant information to the calling client is preferrable.
</para>
<para>
The Neo4j server has two built in extension mechanisms.
It is possible to add extensions to existing endpoints
like the graph database, nodes or relationships - add new URIs or methods to those. This is achieved by
writing <ulink url="http://docs.neo4j.org/chunked/milestone/server-plugins.html">Server Plugins</ulink>.
</para>
<para>
For complete freedom in your implementation an <ulink
url="http://docs.neo4j.org/chunked/milestone/server-unmanaged-extensions.html">unmanaged extension</ulink>
might be the right solution. Unmanaged
extensions are <ulink url="http://jersey.java.net/">jersey</ulink> resource implementations.
The resources constructors or methods can get the <code>GraphDatabaseService</code> injected to execute the
necessary operations and return appropriate Representations.
</para>
<para>
Both kinds of extensions have to be packaged as a jar and added to the Neo4j-Server's plugin directory.
Server Plugins are picked up at server startup when they provide the necessary
<code>META-INF.services/org.neo4j.server.plugins.ServerPlugin</code> file for Javas service loader mechanism.
Unmanaged extensions have to be registered with the neo4j-server configuration.
<programlisting language="ini"><![CDATA[
org.neo4j.server.thirdparty_jaxrs_classes=com.example.mypackage=/my-context
]]></programlisting>
</para>
<para>
Integrating Spring Data Graph into this setup is not so trivial because the graph database is not created
by the spring context but already provided by the Neo4j-server. But a correctly set up and loaded
spring context ist the requirement for spring data graph to work. By using the lifecycle support of
Neo4j server extendsions it is possible to register the provided graph database with the
spring configuration and also to expose certain spring beans (e.g. finderFactory, graphDatabaseContext) to be
injected via jersey into subsequent resources.
</para>
<para>
This can be achieved by subclassing SpringPluginInitializer and providing the context-locations and the
beans that should be exposed. The <code>SpringPluginInitializer</code> merges the graph database service
with the spring configuration and registers the named beans as jersey Injectables.
<programlisting language="java"><![CDATA[
public class HelloWorldInitializer extends SpringPluginInitializer {
public HelloWorldInitializer() {
super(new String[]{"spring/helloWorldServer-Context.xml"}, "worldRepository","finderFactory");
}
}
]]></programlisting>
It is still necessary to list the initializer fully qualified class name in a
file named META-INF/services/org.neo4j.server.plugins.PluginLifecycle. Then the Neo4j Server can pick up
and run the initialization classes before the the extensions are loaded.
</para>
</section>
<section>
<title>Using Spring Data Graph as a REST-Client</title>
<para>
Spring Data Graph can use the Java Rest Bindings which come as a drop in replacement for the
GraphDatabaseService API. Just by configuring the <code>graphDatabaseService</code> to be a
<code>RestGraphDatabaseService</code> pointing to the correct URL, a Neo4j-REST server can be used.
</para>
<note>
<para>
The Java REST Driver is still under development, so performance and functionality might not be en
par with Spring Data Graph.
</para>
</note>
</section>
</chapter>

View File

@@ -2,19 +2,28 @@
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<section id="reference_programming-model:indexing">
<title>Indexing</title>
<para>
The Neo4j graph database can use different index providers for exact lookups and fulltext searches. Lucene is
used as a index provider implementation. There is support for distinct indexes for nodes and relationships
which can be configured to be of fulltext or exact types.
</para>
<section>
<title>Exact and Numeric Index</title>
<para>
Using the standard Neo4j API, Nodes and Relationships and their indexed field-value combinations
have to be added manually to the appropriate index. When using Spring Data Graph, this task is simplified by
eased by applying an <code>@Indexed</code> annotation on entity fields. This will result in updates to the
index on every change. Numerical fields are indexed numerically so that they are available for range queries.
All other fields are indexed with their string representation. The @Indexed annotation can also set the
index-name to be used. If @Indexed annotates the entity class, the index-name for the whole entity is preset
to that value. Not providing index names defaults them to "node" and "relationship" respectively.
index on every change.
</para><para>
Numerical fields are indexed numerically so that they are available for range queries.
All other fields are indexed with their string representation.
</para><para>
The @Indexed annotation can also set the
index-name to be used the default index name is the simple class name of the entity. So the same field names
from different classes don't end up in the same index by default. That would return different domain objects
for a single index query.
</para>
<para>
Query access to the index happens with the Node- and RelationshipFinders that are created via an instance of
@@ -35,16 +44,6 @@ class Person {
}
@NodeEntity
@Indexed(indexName="groups")
class Group {
@Indexed
String name;
@RelatedTo(elementClass = Person.class, type = "people" )
Set<Person> people;
}
NodeFinder<Person> finder = finderFactory.createNodeEntityFinder(Person.class);
// exact finder
@@ -55,14 +54,82 @@ for (Person middleAgedDeveloper : finder.findAllByRange(null, "age", 20, 40)) {
Developer developer=middleAgedDeveloper.projectTo(Developer.class);
}
]]></programlisting>
<para>
Neo4jTemplate also offers index support, providing auto-indexing for fields at creation time of nodes and
relationships. There is an <code>autoIndex</code> method that can also add indexes for a set of fields in one
go.
</para>
<para>
For querying the index, the template offers query-methods that take either the exact match parameters or a query
object / query expression and push the results wrapped uniformly as Paths to the supplied
<code>PathMapper</code> to be converted or collected.
</para>
</section>
<section>
<title>Fulltext Indexes</title>
<para>
Spring Data Graph also supports full-text indexes. By default indexed fields are stored in an exact-lookup
index. To have them analyzed and prepared for fulltext search, the <code>@Indexed</code> annotation has
the boolean <code>fulltext</code> attribute. Please note that fulltext-indexes require a separate index name
as the fulltext-configuration is stored in the index itself.
</para>
<para>
Access to the fulltext index is provided by the <code>findAllByQuery</code> method of the finders. Wildcard
like * are allowed. Otherwise the fulltext querying rules of the underlying index provider apply. (In most
cases this will be lucene.
</para>
<para>
<programlisting language="java"><![CDATA[
@NodeEntity
class Person {
@Indexed(indexName = "person-name", fulltext=true)
String name;
}
NodeFinder<Person> finder = finderFactory.createNodeEntityFinder(Person.class);
// exact finder
Person mark = finder.findAllByQuery("people-search","name","ma*");
]]></programlisting>
</para>
<note>
<para>
Please note that indexes are currently created on demand, so whenever an index that doesn't exist
is requested from a query or get operation it is created. This is subject to change but has currently
the implication that those indexes won't be configured as fulltext which causes subsequent fulltext-
updates to those indexes to fail.
</para>
</note>
</section>
<section>
<title>Raw Index Access</title>
<para>The raw index for a domain class is also available from <code>GraphDatabaseContext</code> via the
<code>getIndex</code> method. The second parameter is optional and takes the index-name if it doesn't default
to the simple domain class name. It returns the Index implementation that is provided by Neo4j.
<programlisting language="java"><![CDATA[
@Autowired GraphDatabaseContext gdc;
// exact index
Index<Node> personIndex=gdc.getIndex(Person.class,null);
personIndex.add(node,"name","Mark");
Index<Node> namedPersonIndex=gdc.getIndex(Person.class,"people");
namedPersonIndex.get("name","Mark");
// complex range & sort query
namedPersonIndex.query( new QueryContext( NumericRangeQuery.newÍntRange( "age", 20, 40, true, true ) )
.sort( new Sort( new SortField( "age", SortField.INT, false ) ) ) );
// fulltext index
Index<Node> personFulltextIndex=gdc.getIndex(Person.class,"person-name",true);
namedPersonIndex.query("name","Ma*");
namedPersonIndex.query("{name:Ma*}");
]]></programlisting>
</para>
</section>
<section>
<title>Indexing in Neo4jTemplate</title>
<para>
Neo4jTemplate also offers index support, providing auto-indexing for fields at creation time of nodes and
relationships. There is an <code>autoIndex</code> method that can also add indexes for a set of fields in one
go.
</para>
<para>
For querying the index, the template offers query-methods that take either the exact match parameters or a query
object / query expression and push the results wrapped uniformly as Paths to the supplied
<code>PathMapper</code> to be converted or collected.
</para>
</section>
</section>