neo4j cypher查询注释语法,用于搜索朋友关系的朋友

时间:2015-01-15 01:35:32

标签: neo4j cypher spring-boot spring-data-neo4j

我是neo4j和cypher的新手,我正在努力解决下面的问题。

我的存储库界面中有一个方法,在给定成员ID的情况下返回朋友列表的朋友。我的POJO是会员,其中包含会员类型的朋友列表。

@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);

我正在使用来自给定依赖项的neo4j版本:

<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>

这是我得到的堆栈跟踪:

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)

我已将查询更新为:

@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)")  

这导致没有错误,但是我没有得到任何结果。我期待2条记录。

我的neo4j图包括:1个记录[会员A],其中id匹配{id},A有1个朋友B,B有2个朋友。我希望B的朋友能够通过查询返回。

这是我的简单测试用例:

public void testQuery(){
    Member A = new Member("test@gmail.com");
    Member B = new Member("testb@gmail.com");

    Member friend = new Member("jau@gmail.com");
    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("kim@gmail.com");
    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());

}

也许我如何定义我的数据模型会有所帮助:

@NodeEntity
public class Member {

    @GraphId
    private Long id;

    @Indexed(unique = true)
    private String email;

    @RelatedTo(type = "FRIEND", direction = Direction.BOTH)
    @Fetch
    Set<Member> friends;

1 个答案:

答案 0 :(得分:0)

id属性值应该是字符串还是整数?您的Cypher查询会在{id}周围添加引号,因此它只会匹配id具有字符串值的节点。请尝试删除{id}周围的引号。

[EDITED]

此外,您更新的查询似乎没问题。我创建了一个成功找到两个friend_of_friend节点的console。我已将{id}替换为硬编码的数字(因为控制台不支持参数),并更改了`RETURN子句,以便您可以确定正在返回哪些节点。

MATCH (me:Member { id: 123 })-[:FRIEND*2..2]-(friend_of_friend:Member)
WHERE NOT (me)-[:FRIEND]-(friend_of_friend)
RETURN friend_of_friend.id