I am very new to neo4j and cypher and I am struggling with the query below.
I have a method in my repository interface that returns friend of friends list given a member's ID. My POJO is Member and in it is a list of friends of type Member.
@Query("MATCH path=(me:Member {id: '{id}'})-[f:FRIEND]->(friend:Member) WITH [x in nodes(path) | id(x) AS friends] WHERE id(me) in friends MATCH friends-[ff:FRIEND]->(fof:Member) return fof")
public Collection<Member> findByIdFriendsOfFriend(@Param("id") Long id);
I am using neo4j version from the given dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j-rest</artifactId>
<version>3.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
</dependency>
Here is the stack trace I am getting:
org.neo4j.rest.graphdb.RestResultException: Invalid input 'S': expected 'n/N' (line 1, column 97)
"MATCH path=(me:Member {id: '{id}'})-[f:FRIEND]->(friend:Member) WITH [x in nodes(path) | id(x) AS friends] WHERE id(me) in friends MATCH friends-[ff:FRIEND]->(fof:Member) return fof"
^ at
SyntaxException
org.neo4j.cypher.internal.compiler.v2_1.parser.CypherParser$$anonfun$parse$1.apply(CypherParser.scala:57)
org.neo4j.cypher.internal.compiler.v2_1.parser.CypherParser$$anonfun$parse$1.apply(CypherParser.scala:47)
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
scala.collection.immutable.List.foreach(List.scala:318)
scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
scala.collection.AbstractTraversable.map(Traversable.scala:105)
org.neo4j.cypher.internal.compiler.v2_1.parser.CypherParser.parse(CypherParser.scala:46)
org.neo4j.cypher.internal.compiler.v2_1.CypherCompiler.prepareQuery(CypherCompiler.scala:107)
org.neo4j.cypher.internal.CypherCompiler$$anon$2$$anonfun$5.apply(CypherCompiler.scala:85)
org.neo4j.cypher.internal.CypherCompiler$$anon$2$$anonfun$5.apply(CypherCompiler.scala:85)
scala.util.Try$.apply(Try.scala:161)
org.neo4j.cypher.internal.CypherCompiler$$anon$2.<init>(CypherCompiler.scala:85)
org.neo4j.cypher.internal.CypherCompiler.parseQuery(CypherCompiler.scala:84)
org.neo4j.cypher.ExecutionEngine$$anonfun$parseQuery$1.apply(ExecutionEngine.scala:81)
org.neo4j.cypher.ExecutionEngine$$anonfun$parseQuery$1.apply(ExecutionEngine.scala:81)
org.neo4j.cypher.internal.LRUCache.getOrElseUpdate(LRUCache.scala:35)
org.neo4j.cypher.ExecutionEngine.parseQuery(ExecutionEngine.scala:81)
org.neo4j.cypher.internal.ServerExecutionEngine.isPeriodicCommit(ServerExecutionEngine.scala:34)
org.neo4j.cypher.javacompat.internal.ServerExecutionEngine.isPeriodicCommit(ServerExecutionEngine.java:56)
org.neo4j.server.rest.web.CypherService.cypher(CypherService.java:99)
java.lang.reflect.Method.invoke(Method.java:483)
org.neo4j.server.rest.transactional.TransactionalRequestDispatcher.dispatch(TransactionalRequestDispatcher.java:139)
java.lang.Thread.run(Thread.java:745)
at org.neo4j.rest.graphdb.ExecutingRestAPI.query(ExecutingRestAPI.java:569)
at org.neo4j.rest.graphdb.RestAPIFacade.query(RestAPIFacade.java:235)
at org.neo4j.rest.graphdb.query.RestCypherQueryEngine.query(RestCypherQueryEngine.java:50)
at org.springframework.data.neo4j.rest.SpringRestCypherQueryEngine.query(SpringRestCypherQueryEngine.java:48)
at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.dispatchQuery(GraphRepositoryQuery.java:107)
at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery$1.doWithGraph(GraphRepositoryQuery.java:89)
at org.springframework.data.neo4j.support.Neo4jTemplate.doExecute(Neo4jTemplate.java:457)
at org.springframework.data.neo4j.support.Neo4jTemplate.access$000(Neo4jTemplate.java:87)
at org.springframework.data.neo4j.support.Neo4jTemplate$2.doInTransaction(Neo4jTemplate.java:471)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at org.springframework.data.neo4j.support.Neo4jTemplate.exec(Neo4jTemplate.java:468)
at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.execute(GraphRepositoryQuery.java:83)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:421)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:381)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$DefaultMethodInvokingMethodInterceptor.invoke(RepositoryFactorySupport.java:512)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy110.findByIdFriendsOfFriend(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:201)
at com.sun.proxy.$Proxy115.findByIdFriendsOfFriend(Unknown Source)
at com.shop.test.repository.Neo4jRepositoryTest.testQuery(Neo4jRepositoryTest.java:88)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:217)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
I have since updated my query to:
@Query("MATCH (me:Member { id: '{id}' })-[:FRIEND*2..2]-(friend_of_friend:Member) WHERE NOT (me)-[:FRIEND]-(friend_of_friend) RETURN labels(friend_of_friend)")
This results in no errors however I do not get any results back. I expect 2 records.
My neo4j graph consist of : 1 record [Member A] in which id matches {id} and A has 1 friend B and B has 2 friends. I expect B's friends to be return by the query.
Here is my simple test case:
public void testQuery(){
Member A = new Member("[email protected]");
Member B = new Member("[email protected]");
Member friend = new Member("[email protected]");
friend.addFriend(A);
friend.addFriend(B);
Member returnfriend = template.save(friend);
System.out.println("friend id " + returnfriend.getId());
Assert.assertNotNull(returnfriend.getId());
Assert.assertEquals(2, returnfriend.getFriends().size());
Member member = new Member("[email protected]");
member.addFriend(returnfriend);
member = template.save(member);
//Page<Member> found = memberRepository.findByIdFriendsOfFriend(member.getId(), new PageRequest(0, 2));
Collection<Member> found = memberRepository.findByIdFriendsOfFriend(member.getId());
Assert.assertNotNull(found);
for(Member m : found){
if(m != null){
if(m.getEmail()!=null){
System.out.println(m.getEmail());
}
System.out.println(m.getId());
}else{
System.out.println("m is null");
}
}
Assert.assertEquals(2, found.size());
}
Maybe How I am defining my data model will help:
@NodeEntity
public class Member {
@GraphId
private Long id;
@Indexed(unique = true)
private String email;
@RelatedTo(type = "FRIEND", direction = Direction.BOTH)
@Fetch
Set<Member> friends;