DATAGRAPH-406 Removing Gremlin Dependency
This commit is contained in:
@@ -109,7 +109,7 @@ try {
|
||||
<li><code>@Indexed([fulltext=true],[indexName=name])</code> Auto-Indexing</li>
|
||||
<li><code>@RelatedTo([direction=Direction], [type=TYPE])</code> define type and direction of relationship on <code>Entity, Iterable<E>, Set<E></code> fields</li>
|
||||
<li><code>@RelatedToVia([direction=Direction], [type=TYPE])</code> like <code>@RelatedTo,</code> but targets Relationship-Entities</li>
|
||||
<li><code>@Query(query, [type=QueryType])</code> computed field, executes graph query in Cypher or Gremlin</li>
|
||||
<li><code>@Query(query, [type=QueryType])</code> computed field, executes graph query in Cypher</li>
|
||||
<li><code>@GraphTraversal(traversal=~TraversalBuilder.class, [elementClass=Person.class])</code> computed field, executes traversal starting from entity-node</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -160,7 +160,7 @@ interface MovieRepository extends GraphRepository<Movie> {
|
||||
<div class="note">
|
||||
<h3>Neo4jTemplate</h3>
|
||||
<ul><li>convenience methods for graph operations, transaction and exception handling</li>
|
||||
<li>index lookups, cypher and gremlin queries, traversal execution with fluent result converter API</li>
|
||||
<li>index lookups, cypher queries, traversal execution with fluent result converter API</li>
|
||||
<li>preconfigured and customizable conversion of results to a variety of types</li></ul>
|
||||
</div>
|
||||
<div class="note">
|
||||
|
||||
3
pom.xml
3
pom.xml
@@ -42,9 +42,6 @@
|
||||
|
||||
<neo4j.spatial.version>0.12-neo4j-2.0.0-M06</neo4j.spatial.version>
|
||||
<neo4j.graph-collections.version>0.7.1-neo4j-2.0.0-M06</neo4j.graph-collections.version>
|
||||
<blueprints.version>1.2</blueprints.version>
|
||||
<gremlin.version>1.5</gremlin.version>
|
||||
<pipes.version>1.5</pipes.version>
|
||||
<neo4j-cypher-dsl.version>2.0.0-M06</neo4j-cypher-dsl.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -147,33 +147,6 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-core</artifactId>
|
||||
<version>${blueprints.version}</version>
|
||||
<scope>test</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-neo4j-graph</artifactId>
|
||||
<version>${blueprints.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-management</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -36,9 +36,6 @@ public interface PersonRepository extends GraphRepository<Person>, NamedIndexRep
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembers(@Param("p_team") Group team);
|
||||
|
||||
@Query(value = "g.v(team).out('persons')", type = QueryType.Gremlin)
|
||||
Iterable<Person> findAllTeamMembersGremlin(@Param("team") Group team);
|
||||
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member.name,member.age")
|
||||
Iterable<Map<String,Object>> findAllTeamMemberData(@Param("p_team") Group team);
|
||||
|
||||
|
||||
@@ -60,13 +60,6 @@ public class GraphRepositoryTests extends EntityTestBase {
|
||||
Iterable<Person> teamMembers = personRepository.findAllTeamMembers(testTeam.sdg);
|
||||
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil));
|
||||
}
|
||||
@Test
|
||||
@Transactional
|
||||
@Ignore
|
||||
public void testFindIterableOfPersonWithQueryAnnotationAndGremlin() {
|
||||
Iterable<Person> teamMembers = personRepository.findAllTeamMembersGremlin(testTeam.sdg);
|
||||
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support.query;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.neo4j.helpers.collection.MapUtil;
|
||||
import org.springframework.data.neo4j.annotation.QueryType;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.aspects.support.EntityTestBase;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.support.DelegatingGraphDatabase;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 13.06.11
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml"})
|
||||
@Transactional
|
||||
@Ignore
|
||||
public class GremlinQueryEngineTests extends EntityTestBase {
|
||||
private QueryEngine<Object> queryEngine;
|
||||
private Person michael;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
GraphDatabase graphDatabase = createGraphDatabase();
|
||||
testTeam.createSDGTeam();
|
||||
queryEngine = graphDatabase.queryEngineFor(QueryType.Gremlin);
|
||||
michael = testTeam.michael;
|
||||
}
|
||||
|
||||
protected GraphDatabase createGraphDatabase() throws Exception {
|
||||
final DelegatingGraphDatabase graphDatabase = new DelegatingGraphDatabase(neo4jTemplate.getGraphDatabaseService());
|
||||
graphDatabase.setConversionService(conversionService);
|
||||
return graphDatabase;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
@Transactional
|
||||
public void testQueryList() throws Exception {
|
||||
final String queryString = "t = new Table(); [g.v(michael),g.v(david)].each{ n -> n.as('person.name').as('person.age').table(t,['person.name','person.age']){ it.age }{ it.name }.iterate()}; t;" ;
|
||||
final Collection<Object> result = IteratorUtil.asCollection(queryEngine.query(queryString, MapUtil.map("michael", getNodeId(michael), "david", getNodeId(testTeam.david))));
|
||||
|
||||
assertEquals(asList(testTeam.simpleRowFor(michael, "person"), testTeam.simpleRowFor(testTeam.david, "person")), result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,10 +29,7 @@ Import-Template:
|
||||
javax.persistence.*;version="[1.0.0, 3.0.0)";resolution:=optional,
|
||||
javax.persistence.spi.*;version="[1.0.0, 3.0.0)";resolution:=optional,
|
||||
javax.transaction.*;version="[1.0.1, 2.0.0)";resolution:=optional,
|
||||
com.tinkerpop.blueprints.*;version="[0.8,1.0)";resolution:=optional,
|
||||
com.tinkerpop.gremlin.*;version="[1.1,2.0)";resolution:=optional,
|
||||
com.tinkerpop.pipes.util.*;version="[0.8,1.0)";resolution:=optional
|
||||
Import-Package:
|
||||
Import-Package:
|
||||
sun.reflect;version="0";resolution:=optional,
|
||||
net.sf.cglib.proxy;version="[2.2.0,3.0.0)",
|
||||
net.sf.cglib.core;version="[2.2.0,3.0.0)",
|
||||
|
||||
@@ -124,13 +124,6 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--dependency>
|
||||
<groupId>org.neo4j.server.plugin</groupId>
|
||||
<artifactId>neo4j-gremlin-plugin</artifactId>
|
||||
<version>1.9.2</version>
|
||||
<optional>true</optional>
|
||||
<scope>test</scope>
|
||||
</dependency-->
|
||||
<dependency>
|
||||
<groupId>org.neo4j.app</groupId>
|
||||
<artifactId>neo4j-server</artifactId>
|
||||
@@ -185,36 +178,6 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--dependency>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-core</artifactId>
|
||||
<version>${blueprints.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-neo4j-graph</artifactId>
|
||||
<version>${blueprints.version}</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-management</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.gremlin</groupId>
|
||||
<artifactId>gremlin-groovy</artifactId>
|
||||
<version>${gremlin.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency-->
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-configuration</groupId>
|
||||
<artifactId>commons-configuration</artifactId>
|
||||
|
||||
@@ -17,17 +17,14 @@ package org.springframework.data.neo4j.rest;
|
||||
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.rest.graphdb.RestAPI;
|
||||
import org.neo4j.rest.graphdb.RestAPIFacade;
|
||||
import org.neo4j.rest.graphdb.entity.RestNode;
|
||||
import org.neo4j.rest.graphdb.index.RestIndex;
|
||||
import org.neo4j.rest.graphdb.index.RestIndexManager;
|
||||
import org.neo4j.rest.graphdb.query.RestCypherQueryEngine;
|
||||
import org.neo4j.rest.graphdb.query.RestGremlinQueryEngine;
|
||||
import org.neo4j.rest.graphdb.transaction.NullTransaction;
|
||||
import org.neo4j.rest.graphdb.transaction.NullTransactionManager;
|
||||
import org.neo4j.rest.graphdb.traversal.RestTraversalDescription;
|
||||
import org.neo4j.rest.graphdb.util.Config;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.neo4j.annotation.QueryType;
|
||||
@@ -114,7 +111,6 @@ public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDat
|
||||
public <T> QueryEngine<T> queryEngineFor(QueryType type, final ResultConverter resultConverter) {
|
||||
switch (type) {
|
||||
case Cypher: return (QueryEngine<T>)new SpringRestCypherQueryEngine(new RestCypherQueryEngine(getRestAPI(), new SpringResultConverter(resultConverter)));
|
||||
case Gremlin: return (QueryEngine<T>)new SpringRestGremlinQueryEngine(new RestGremlinQueryEngine(getRestAPI(),new SpringResultConverter(resultConverter)));
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown Query Engine Type "+type);
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.rest;
|
||||
|
||||
|
||||
import org.neo4j.rest.graphdb.query.RestGremlinQueryEngine;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class SpringRestGremlinQueryEngine implements QueryEngine<Object> {
|
||||
|
||||
public static final Logger log = LoggerFactory.getLogger(SpringRestGremlinQueryEngine.class);
|
||||
|
||||
private final RestGremlinQueryEngine restGremlinQueryEngine;
|
||||
|
||||
public SpringRestGremlinQueryEngine(RestGremlinQueryEngine restGremlinQueryEngine) {
|
||||
this.restGremlinQueryEngine = restGremlinQueryEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpringRestResult<Object> query(String statement, Map<String, Object> params) {
|
||||
if (log.isDebugEnabled()) log.debug(String.format("Executing remote gremlin query: %s params %s",statement,params));
|
||||
|
||||
return new SpringRestResult<Object>(restGremlinQueryEngine.query(statement, params));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.rest.support;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.aspects.support.query.GremlinQueryEngineTests;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.rest.SpringRestGraphDatabase;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 23.06.11
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml",
|
||||
"classpath:RestTests-context.xml"})
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
@Ignore
|
||||
public class RestGremlinQueryEngineTests extends GremlinQueryEngineTests {
|
||||
|
||||
@Autowired
|
||||
SpringRestGraphDatabase restGraphDatabase;
|
||||
|
||||
@BeforeClass
|
||||
public static void startDb() throws Exception {
|
||||
RestTestBase.startDb();
|
||||
}
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
RestTestBase.cleanDb();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutdownDb() {
|
||||
RestTestBase.shutdownDb();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphDatabase createGraphDatabase() throws Exception {
|
||||
restGraphDatabase.setConversionService(conversionService);
|
||||
return restGraphDatabase;
|
||||
}
|
||||
}
|
||||
@@ -219,37 +219,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-core</artifactId>
|
||||
<version>${blueprints.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.blueprints</groupId>
|
||||
<artifactId>blueprints-neo4j-graph</artifactId>
|
||||
<version>${blueprints.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-management</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tinkerpop.gremlin</groupId>
|
||||
<artifactId>gremlin-groovy</artifactId>
|
||||
<version>${gremlin.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -21,5 +21,5 @@ package org.springframework.data.neo4j.annotation;
|
||||
* @since 25.07.11
|
||||
*/
|
||||
public enum QueryType {
|
||||
Cypher, Gremlin
|
||||
Cypher
|
||||
}
|
||||
|
||||
@@ -104,12 +104,12 @@ public interface GraphDatabase {
|
||||
TraversalDescription traversalDescription();
|
||||
|
||||
/**
|
||||
* returns a query engine for the provided type (Cypher or Gremlin) which is initialized with the default result converter
|
||||
* returns a query engine for the provided type (Cypher) which is initialized with the default result converter
|
||||
*/
|
||||
<T> QueryEngine<T> queryEngineFor(QueryType type);
|
||||
|
||||
/**
|
||||
* returns a query engine for the provided type (Cypher or Gremlin) which is initialized with the provided result converter
|
||||
* returns a query engine for the provided type (Cypher) which is initialized with the provided result converter
|
||||
*/
|
||||
<T> QueryEngine<T> queryEngineFor(QueryType type, ResultConverter resultConverter);
|
||||
|
||||
|
||||
@@ -149,10 +149,8 @@ public class GraphQueryMethod extends QueryMethod {
|
||||
switch (queryAnnotation.type()) {
|
||||
case Cypher:
|
||||
return new CypherGraphRepositoryQuery(this, template);
|
||||
case Gremlin:
|
||||
return new GremlinGraphRepositoryQuery(this, template);
|
||||
default:
|
||||
throw new IllegalStateException("@Query Annotation has to be configured as Cypher or Gremlin Query");
|
||||
throw new IllegalStateException("@Query Annotation has to be configured as Cypher Query");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.repository.query;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.neo4j.annotation.QueryType;
|
||||
import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 31.10.11
|
||||
*/
|
||||
class GremlinGraphRepositoryQuery extends GraphRepositoryQuery {
|
||||
|
||||
private QueryEngine queryEngine;
|
||||
|
||||
public GremlinGraphRepositoryQuery(GraphQueryMethod queryMethod, final Neo4jTemplate template) {
|
||||
super(queryMethod, template);
|
||||
}
|
||||
|
||||
protected QueryEngine getQueryEngine() {
|
||||
if (this.queryEngine !=null) return queryEngine;
|
||||
this.queryEngine = getTemplate().queryEngineFor(QueryType.Gremlin);
|
||||
return this.queryEngine;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,6 @@ import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.support.index.NoSuchIndexException;
|
||||
import org.springframework.data.neo4j.support.query.ConversionServiceQueryResultConverter;
|
||||
import org.springframework.data.neo4j.support.query.CypherQueryEngine;
|
||||
import org.springframework.data.neo4j.support.query.GremlinQueryEngine;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -59,7 +58,6 @@ public class DelegatingGraphDatabase implements GraphDatabase {
|
||||
private ConversionService conversionService;
|
||||
private ResultConverter resultConverter;
|
||||
private volatile QueryEngine<Object> cypherQueryEngine;
|
||||
private volatile QueryEngine<Object> gremlinQueryEngine;
|
||||
|
||||
public DelegatingGraphDatabase(final GraphDatabaseService delegate) {
|
||||
this(delegate,null);
|
||||
@@ -90,7 +88,6 @@ public class DelegatingGraphDatabase implements GraphDatabase {
|
||||
|
||||
private void reinitQueryEngines() {
|
||||
if (cypherQueryEngine != null) this.cypherQueryEngine = queryEngineFor(QueryType.Cypher, resultConverter, true);
|
||||
if (gremlinQueryEngine != null) this.gremlinQueryEngine = queryEngineFor(QueryType.Gremlin, resultConverter, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,14 +208,6 @@ public class DelegatingGraphDatabase implements GraphDatabase {
|
||||
}
|
||||
return (QueryEngine<T>) cypherQueryEngine;
|
||||
}
|
||||
case Gremlin: {
|
||||
if (reinit || gremlinQueryEngine==null) {
|
||||
synchronized (this) {
|
||||
if (reinit || gremlinQueryEngine==null) gremlinQueryEngine=createGremlinQueryEngine(resultConverter);
|
||||
}
|
||||
}
|
||||
return (QueryEngine<T>) gremlinQueryEngine;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown Query Engine Type "+type);
|
||||
}
|
||||
@@ -228,13 +217,6 @@ public class DelegatingGraphDatabase implements GraphDatabase {
|
||||
return queryEngineFor(type,resultConverter,false);
|
||||
}
|
||||
|
||||
private <T> QueryEngine<T> createGremlinQueryEngine(ResultConverter resultConverter) {
|
||||
if (!ClassUtils.isPresent("com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jGraph", getClass().getClassLoader())) {
|
||||
return new FailingQueryEngine<T>("Gremlin");
|
||||
}
|
||||
return (QueryEngine<T>) new GremlinQueryEngine(delegate,resultConverter);
|
||||
}
|
||||
|
||||
private <T> QueryEngine<T> createCypherQueryEngine(ResultConverter resultConverter) {
|
||||
if (!ClassUtils.isPresent("org.neo4j.cypher.javacompat.ExecutionEngine", getClass().getClassLoader())) {
|
||||
return new FailingQueryEngine<T>("Cypher");
|
||||
|
||||
@@ -528,13 +528,6 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
|
||||
return queryEngine.query(statement, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Result<Object> execute(String statement, Map<String, Object> params) {
|
||||
notNull(statement, "statement");
|
||||
return queryEngineFor(QueryType.Gremlin).query(statement, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Path> traverse(Object start, TraversalDescription traversal) {
|
||||
return traverse((Node) getPersistentState(start), traversal);
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.support.query;
|
||||
|
||||
import com.tinkerpop.blueprints.pgm.Edge;
|
||||
import com.tinkerpop.blueprints.pgm.Vertex;
|
||||
import com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jEdge;
|
||||
import com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jGraph;
|
||||
import com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jVertex;
|
||||
import com.tinkerpop.pipes.util.structures.Row;
|
||||
import com.tinkerpop.pipes.util.structures.Table;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.helpers.collection.IterableWrapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.script.*;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class GremlinExecutor {
|
||||
|
||||
public static final Logger log = LoggerFactory.getLogger(GremlinExecutor.class);
|
||||
public static final int REFRESH_ENGINE_COUNT = 10000;
|
||||
private static final String GRAPH_VARIABLE = "g";
|
||||
private volatile ScriptEngine engine;
|
||||
|
||||
private ScriptEngine createScriptEngine() {
|
||||
return new ScriptEngineManager().getEngineByName("gremlin-groovy");
|
||||
}
|
||||
|
||||
private static final AtomicInteger executionCount = new AtomicInteger();
|
||||
private final GraphDatabaseService graphDatabaseService;
|
||||
|
||||
public GremlinExecutor(GraphDatabaseService graphDatabaseService) {
|
||||
this.graphDatabaseService = graphDatabaseService;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterable<Object> query(String statement, Map<String,Object> params) {
|
||||
try {
|
||||
if (log.isDebugEnabled()) log.debug(String.format("Executing gremlin query: %s params %s",statement,params));
|
||||
|
||||
final Bindings bindings = createBindings(params);
|
||||
final ScriptEngine engine = engine();
|
||||
final Object result = engine.eval(statement, bindings);
|
||||
return getRepresentation(result);
|
||||
} catch (final ScriptException e) {
|
||||
throw new RuntimeException("Error executing statement " + statement, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Bindings createBindings(Map<String, Object> params) {
|
||||
final Bindings bindings = new SimpleBindings();
|
||||
bindings.put(GRAPH_VARIABLE, new Neo4jGraph(graphDatabaseService,false));
|
||||
if (params==null) return bindings;
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
bindings.put(entry.getKey(),entry.getValue());
|
||||
}
|
||||
return bindings;
|
||||
}
|
||||
|
||||
private ScriptEngine engine() {
|
||||
if (engine == null || executionCount.incrementAndGet() > REFRESH_ENGINE_COUNT) {
|
||||
executionCount.set(0);
|
||||
this.engine = createScriptEngine();
|
||||
}
|
||||
return this.engine;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Iterable getRepresentation(final Object result) {
|
||||
if (result instanceof Iterable) {
|
||||
if (result instanceof Table) {
|
||||
final Table table = (Table) result;
|
||||
return new IterableWrapper<Map<String,Object>,Row>(table) {
|
||||
@Override
|
||||
protected Map<String, Object> underlyingObjectToObject(Row row) {
|
||||
Map<String,Object> result=new LinkedHashMap<String, Object>();
|
||||
for (String column : table.getColumnNames()) {
|
||||
result.put(column, row.getColumn(column));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new IterableWrapper((Iterable) result) {
|
||||
@Override
|
||||
protected Object underlyingObjectToObject(Object object) {
|
||||
return getSingleResult(object);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return Collections.singleton(getSingleResult(result));
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getSingleResult(Object result) {
|
||||
if (result instanceof Vertex) {
|
||||
return ((Neo4jVertex) result).getRawVertex();
|
||||
} else if (result instanceof Edge) {
|
||||
return ((Neo4jEdge) result).getRawEdge();
|
||||
} else if (result instanceof Neo4jGraph) {
|
||||
return ((Neo4jGraph) result).getRawGraph();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.support.query;
|
||||
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.data.neo4j.conversion.DefaultConverter;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
|
||||
import org.springframework.data.neo4j.conversion.ResultConverter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GremlinQueryEngine implements QueryEngine<Object> {
|
||||
|
||||
private final GremlinExecutor gremlinExecutor;
|
||||
private final ResultConverter resultConverter;
|
||||
|
||||
public GremlinQueryEngine(GraphDatabaseService graphDatabaseService) {
|
||||
this(graphDatabaseService, new DefaultConverter());
|
||||
}
|
||||
|
||||
|
||||
public GremlinQueryEngine(GraphDatabaseService graphDatabaseService, ResultConverter resultConverter) {
|
||||
this.resultConverter = resultConverter != null ? resultConverter : new DefaultConverter();
|
||||
this.gremlinExecutor = new GremlinExecutor(graphDatabaseService);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Result<Object> query(String statement, Map<String, Object> params) {
|
||||
try {
|
||||
Iterable<Object> result = gremlinExecutor.query(statement, params);
|
||||
return new QueryResultBuilder<Object>(result,resultConverter);
|
||||
} catch (Exception e) {
|
||||
throw new InvalidDataAccessResourceUsageException("Error executing statement " + statement, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,7 @@ public interface Neo4jOperations {
|
||||
<T extends PropertyContainer> Result<T> lookup(String indexName, Object query);
|
||||
|
||||
/**
|
||||
* Provides a cypher or gremlin query engine set up with a default entity converter.
|
||||
* Provides a cypher query engine set up with a default entity converter.
|
||||
*/
|
||||
<T> QueryEngine<T> queryEngineFor(QueryType type);
|
||||
|
||||
@@ -199,12 +199,6 @@ public interface Neo4jOperations {
|
||||
*/
|
||||
Result<Map<String, Object>> query(String statement, Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* Executes the given Gremlin statement and returns the result packaged as Result as Neo4j types, not
|
||||
* Gremlin types. The Neo4j-Graph is provided as variable "g". Table rows are converted to Map<String,Object>.
|
||||
*/
|
||||
Result<Object> execute(String statement, Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* Traverses the graph starting at the given node with the provided traversal description. The Path's of the
|
||||
* traversal will be packaged into a Result which can be easily converted into Nodes, Relationships or
|
||||
|
||||
@@ -36,9 +36,6 @@ public interface PersonRepository extends GraphRepository<Person>, NamedIndexRep
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembers(@Param("p_team") Group team);
|
||||
|
||||
@Query(value = "g.v(team).out('persons')", type = QueryType.Gremlin)
|
||||
Iterable<Person> findAllTeamMembersGremlin(@Param("team") Group team);
|
||||
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member.name,member.age")
|
||||
Iterable<Map<String,Object>> findAllTeamMemberData(@Param("p_team") Group team);
|
||||
|
||||
|
||||
@@ -216,12 +216,6 @@ public class GraphRepositoryTests {
|
||||
assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david));
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
public void testFindIterableOfPersonWithQueryAnnotationAndGremlin() {
|
||||
Iterable<Person> teamMembers = personRepository.findAllTeamMembersGremlin(testTeam.sdg);
|
||||
assertThat( asCollection( teamMembers ), hasItems(testTeam.michael, testTeam.david, testTeam.emil) );
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
public void testFindPersonWithQueryAnnotation() {
|
||||
Person boss = personRepository.findBoss( testTeam.michael );
|
||||
|
||||
@@ -43,9 +43,6 @@ public interface PersonRepository extends GraphRepository<Person>, NamedIndexRep
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembers(@Param("p_team") Group team);
|
||||
|
||||
@Query(value = "g.v(team).out('persons')", type = QueryType.Gremlin)
|
||||
Iterable<Person> findAllTeamMembersGremlin(@Param("team") Group team);
|
||||
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member.name,member.age")
|
||||
Iterable<Map<String, Object>> findAllTeamMemberData(@Param("p_team") Group team);
|
||||
|
||||
|
||||
@@ -371,12 +371,6 @@ public class EntityNeo4jTemplateTests extends EntityTestBase {
|
||||
final Person result = engine.query("start n=node({self}) return n", map("self", testTeam.michael.getId())).to(Person.class).single();
|
||||
assertEquals(testTeam.michael.getId(), result.getId());
|
||||
}
|
||||
@Test @Transactional
|
||||
public void testQueryEngineForGremlin() throws Exception {
|
||||
final QueryEngine<Result<Object>> engine = neo4jOperations.queryEngineFor(QueryType.Gremlin);
|
||||
final Person result = engine.query("g.v(self)", map("self", testTeam.michael.getId())).to(Person.class).single();
|
||||
assertEquals(testTeam.michael.getId(), result.getId());
|
||||
}
|
||||
|
||||
@Test @Transactional
|
||||
public void testTraverse() throws Exception {
|
||||
|
||||
@@ -328,12 +328,6 @@ public class FullNeo4jTemplateTests {
|
||||
assertSingleResult(node1, neo4jTemplate.query("start n=node(0) match n-[:knows]->m return m", null).to(Node.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void shouldFindNextNodeViaGremlin() throws Exception {
|
||||
assertSingleResult(node1, neo4jTemplate.execute("g.v(0).outE.filter{it.label=='knows'}.inV", null).to(Node.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void shouldGetDirectRelationship() throws Exception {
|
||||
|
||||
@@ -188,12 +188,6 @@ public class Neo4jTemplateApiTests {
|
||||
assertSingleResult(node1, template.query("start n=node(0) match n-->m return m", null).to(Node.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void shouldFindNextNodeViaGremlin() throws Exception {
|
||||
assertSingleResult(node1, template.execute("g.v(0).out", null).to(Node.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetDirectRelationship() throws Exception {
|
||||
assertSingleResult("rel1", template.convert(referenceNode.getRelationships()).to(String.class, new RelationshipNameConverter()));
|
||||
|
||||
@@ -84,10 +84,6 @@ public class SnippetNeo4jTemplateMethodsTests extends DocumentingTestBase {
|
||||
|
||||
// SNIPPET template
|
||||
|
||||
// Gremlin
|
||||
assertEquals(thomas, neo.execute("g.v(person).out('WORKS_WITH')",
|
||||
map("person", mark.getId())).to(Node.class).single());
|
||||
|
||||
// Index lookup
|
||||
assertEquals(thomas, neo.lookup("devs", "name", "Thomas").to(Node.class).single());
|
||||
|
||||
|
||||
@@ -37,10 +37,7 @@ Import-Template:
|
||||
com.mysema.query.annotations.*;version="0";resolution:=optional,
|
||||
com.mysema.query.apt.*;version="0";resolution:=optional,
|
||||
com.mysema.query.types.*;version="0";resolution:=optional,
|
||||
com.tinkerpop.blueprints.*;version="[0.8,1.0)";resolution:=optional,
|
||||
com.tinkerpop.gremlin.*;version="[1.1,2.0)";resolution:=optional,
|
||||
com.tinkerpop.pipes.util.*;version="[0.8,1.0)";resolution:=optional
|
||||
Import-Package:
|
||||
Import-Package:
|
||||
sun.reflect;version="0";resolution:=optional,
|
||||
scala.collection;version="0";resolution:=optional,
|
||||
net.sf.cglib.proxy;version="[2.2.0,3.0.0)",
|
||||
|
||||
@@ -3,20 +3,17 @@
|
||||
<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)
|
||||
* Update tutorial to include some of the new features (cypher)
|
||||
* eclipse / STS setup with m2e, AspectJConfigurator and Weaving enabled etc. https://jira.springsource.org/browse/DATAGRAPH-104
|
||||
|
||||
* fetch-strategies / behaviour
|
||||
* cascading persist/save
|
||||
* @Indexed(level)
|
||||
*
|
||||
* more on Gremlin / Cypher over REST
|
||||
* more on Cypher over REST
|
||||
-->
|
||||
<bookinfo>
|
||||
<title>Good Relationships</title>
|
||||
|
||||
@@ -95,7 +95,7 @@ public void foo( @Context WorldRepository repo ) {
|
||||
<para>
|
||||
Please also keep in mind that performing graph operations via the REST-API is about one order of
|
||||
magnitude slower than local 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.
|
||||
or server-side traversals (<code>RestTraversal</code>) whenever possible for retrieving large sets of data.
|
||||
Future versions of Spring Data Neo4j will use the more performant batch API as well as a binary protocol.
|
||||
</para>
|
||||
<para>
|
||||
@@ -128,7 +128,7 @@ public void foo( @Context WorldRepository repo ) {
|
||||
Your project is now set up to work against a remote Neo4j Server.
|
||||
</para>
|
||||
<para>
|
||||
For traversals and Cypher and Gremlin graph queries it is sensible to forward those to the remote endpoint and execute them there
|
||||
For traversals and Cypher graph queries it is sensible to forward those to the remote endpoint and execute them there
|
||||
instead of walking the graph over the wire. SpringRestGraphDatabase 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. Those methods are also
|
||||
|
||||
@@ -205,35 +205,6 @@ start lucy=node(1000) match lucy-[:ACTS_IN]->movie<-[:ACTS_IN]-co_actor
|
||||
// Recommendations including counts, grouping and sorting
|
||||
start user=node:User(login='micha') match user-[: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 Neo4j 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 Neo4j 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>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
references to other entities this is straightforward.
|
||||
</para>
|
||||
<para>
|
||||
To use advanced functionality like traversals, Cypher and Gremlin, a basic understanding of the graph data model is required.
|
||||
To use advanced functionality like traversals and Cypher, a basic understanding of the graph data model is required.
|
||||
The graph data model is explained in the chapter about Neo4j, see <xref linkend="neo4j" />.
|
||||
</para>
|
||||
<para>
|
||||
@@ -70,7 +70,7 @@
|
||||
(<xref linkend="reference_template"/>) for interacting with
|
||||
the mapped entities and the Neo4j graph database. The operations provided by Spring Data Neo4j - Repositories
|
||||
per mapped entity class are based on the API offered by the Neo4j-Template. It also provides the operations of the Neo4j Core API
|
||||
in a more convenient way. Especially the querying (Indexes, Cypher, Gremlin and Traversals) and result conversion
|
||||
in a more convenient way. Especially the querying (Indexes, Cypher and Traversals) and result conversion
|
||||
facilities allow writing very concise code.
|
||||
</para>
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
</para>
|
||||
<para>
|
||||
Using computed fields that are dynamically backed by graph operations is a bit more involved. First you should know
|
||||
about traversals, Cypher queries and Gremlin expressions.
|
||||
about traversals and Cypher queries.
|
||||
Those are explained in <xref linkend="neo4j" />. Then you can start using virtual, computed fields
|
||||
in your entities <xref linkend="reference_programming-model_projection"/> .
|
||||
</para>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<para>
|
||||
Indexing is used in Neo4j to quickly find nodes and relationships to start graph operations from.
|
||||
Either for manually traversing the graph, using the traversal framework, cypher or gremlin queries
|
||||
Either for manually traversing the graph, using the traversal framework, cypher queries
|
||||
or for "global" graph operations. Indexes are also employed to ensure uniqueness of elements with
|
||||
certain properties.
|
||||
</para>
|
||||
@@ -226,7 +226,7 @@ personFulltextIndex.query("{name:*cha*}");
|
||||
from the approach used in Spring Data Neo4j because it only updates the indexes when the transaction is committed. So the
|
||||
index modifications will only be available after the successful commit.
|
||||
It is possible to use the specific index names <code>node_auto_index</code> and <code>relationship_auto_index</code> when
|
||||
querying indexes in Spring Data Neo4j either with the query methods in template and repositories or via Cypher and Gremlin.
|
||||
querying indexes in Spring Data Neo4j either with the query methods in template and repositories or via Cypher.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
</para>
|
||||
<para>
|
||||
Spring Data Neo4j repositories support annotated and named queries for the Neo4j
|
||||
<ulink url="http://docs.neo4j.org/chunked/milestone/query-lang.html">Cypher</ulink> query-language and
|
||||
<code>Gremlin</code> graph DSL.
|
||||
<ulink url="http://docs.neo4j.org/chunked/milestone/query-lang.html">Cypher</ulink> query-language.
|
||||
</para>
|
||||
<para>
|
||||
Spring Data Neo4j comes with typed repository implementations that provide methods for
|
||||
@@ -136,10 +135,6 @@
|
||||
If it is required that paged results return the correct total count, the <code>@Query</code> annotation can be supplied with a count query in the <code>countQuery</code>
|
||||
attribute. This query is executed separately after the result query and its result is used to populate the <code>totalCount</code> property of the returned Page.
|
||||
</para>
|
||||
<para>
|
||||
Gremlin queries can be used similarly, the <code>@Query</code> annotation would just need a <code>type=QueryType.GREMLIN</code> attribute.
|
||||
Parameters are supported in the same way.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
||||
@@ -44,10 +44,6 @@
|
||||
|
||||
|
||||
|
||||
// Gremlin
|
||||
assertEquals(thomas, neo.execute("g.v(person).out('WORKS_WITH')",
|
||||
map("person", mark.getId())).to(Node.class).single());
|
||||
|
||||
// Index lookup
|
||||
assertEquals(thomas, neo.lookup("devs", "name", "Thomas").to(Node.class).single());
|
||||
|
||||
@@ -123,14 +119,6 @@
|
||||
or converted as needed.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Gremlin Scripts</title>
|
||||
<para>
|
||||
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>Result<Object></code> fit for conversion or usage.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Transactions</title>
|
||||
<para>
|
||||
|
||||
@@ -120,8 +120,6 @@ repositories {
|
||||
Spring Framework (core, context, aop, aspects, tx), AspectJ, Neo4j, and Spring Data Commons. If you
|
||||
already use these (or different versions of these) in your project, then include those dependencies
|
||||
on your own. In this case, please make sure that the versions match.
|
||||
If you want to use Gremlin, please add the dependency (which is optional in SDN)
|
||||
accordingly.
|
||||
</para>
|
||||
<example>
|
||||
<title>Maven dependencies</title>
|
||||
|
||||
@@ -83,8 +83,8 @@
|
||||
<!-- So the first step would be moving away from the aspectj-direct mapping to loading and storing the
|
||||
entities via the repositories which would manage.
|
||||
-->
|
||||
We looked into the different modes of remotely executed operations and found traversals, Cypher and Gremlin queries
|
||||
and index lookups. Most of them already matched our needs but the Cypher and Gremlin approaches were best
|
||||
We looked into the different modes of remotely executed operations and found traversals, Cypher queries
|
||||
and index lookups. Most of them already matched our needs but the Cypher approaches were best
|
||||
suited, because they also handled index operations and allowed to return partial attribute sets and subgraphs.
|
||||
</para>
|
||||
<para>
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
the core API, and declaratively using a query-like
|
||||
<ulink url="http://docs.neo4j.org/chunked/milestone/tutorials-java-embedded-traversal.html">Traversal Description</ulink>. Besides
|
||||
those programmatic traversals there was the powerful graph query language called
|
||||
<ulink url="http://docs.neo4j.org/chunked/milestone/cypher-query-lang.html">Cypher</ulink> and an interesting
|
||||
looking DSL named <ulink url="https://github.com/tinkerpop/gremlin/wiki">Gremlin</ulink>. So lots of ways of working with the graph.
|
||||
<ulink url="http://docs.neo4j.org/chunked/milestone/cypher-query-lang.html">Cypher</ulink>. So lots of ways of working with the graph.
|
||||
</para>
|
||||
<para>
|
||||
We also learned that Neo4j is fully transactional and therefore upholds
|
||||
|
||||
Reference in New Issue
Block a user