updated documentation for server and indexing
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user