springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)

背景

依赖

springboot版本 2.7.10
本地neo4j安装的版本:4.4.19

依赖如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-neo4j</artifactId>
        </dependency>

springboot整合neo4j官网地址:Accessing Data with Neo4j

遇到的问题:

按照官网向导本地运行后,得不到正确的关系

neo4j得到的数据如下:
springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)_第1张图片

            greg = personRepository.findByName(greg.getName());
            greg.worksWith(roy);
            greg.worksWith(craig);
            personRepository.save(greg);

            roy = personRepository.findByName(roy.getName());
            roy.worksWith(craig);
            // We already know that roy works with greg
            personRepository.save(roy);
            log.info("Lookup each person by name...");
            team.stream().forEach(person -> log.info(
                    "\t" + personRepository.findByName(person.getName()).toString()));

上面代码设置了greg的同事是roy,但是查询roy的同事确无法得到greg。
springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)_第2张图片

问题原因分析过程

参考资料1:

首先从官方github找相关issue,有人遇到同类问题,并得到回复如下(问题连接地址:https://stackoverflow.com/questions/68472313/spring-data-neo4j-6-relationship-undirected)。
springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)_第3张图片

也就是说在早期版本,我们可以在关系这里设置UNDIRECTED属性,实现数据间的双向关系。但是后来出于特别的考虑,Neo4j中的关系都是带有方向的关系,不再支持UNDIRECTORY这个属性(Neo4j-OGM支持?)

参考资料2:

官方示例代码在Person实体中也写了注释,大意和上述一致,而且给了连接(https://dzone.com/articles/modelling-data-neo4j)

   /**
     * Neo4j doesn't REALLY have bi-directional relationships. It just means when querying
     * to ignore the direction of the relationship.
     * https://dzone.com/articles/modelling-data-neo4j
     */
    @Relationship(type = "TEAMMATES",direction = Relationship.Direction.INCOMING)
    public Set<Person> teammates;

在这个连接中主要介绍了directed relationships 和 bidirectional relationships之间的区别及具体使用场景。

得到的核心信息如下:
springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)_第4张图片

这里引入了Cypher语法,也就是通过这些语法能够在neo4J中进行增删改查。通过模仿+实践得到结果如下:

MATCH (p1:Person)-[r:TEAMMATES]-(p2:Person) where p1.name = 'Roy' RETURN p2

springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)_第5张图片

此图结果表明,通过 - 查询是忽略关系方向的,能够得到roy的同事有Greg

MATCH (p1:Person)<-[r:TEAMMATES]-(p2:Person) where p1.name = 'Roy' RETURN p2

springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)_第6张图片

此图结果表明,通过 -> 查询是带有关系方向的,得不到roy的同事有Greg

解决办法

自定义查询语句,使用-查询忽略方向即可,修改如下

  @Query("MATCH (p1:Person)-[r:TEAMMATES]-(p2:Person) where p1.name = $name RETURN p2")
    List<Person> findByTeammatesName(String name);

按照官网demo的打印依然无法得到预期结果,因为数据库中虽然支持查询双向关系,但是并不能自动关联到java的Person对象的teammates中,所以我这里手动查询关系,再把关系设置到java实体中并打印即可。
在AccessingDataNeo4jApplication中修改如下

         log.info("-------------Lookup each person by name from neo4j...");
            team.forEach(p -> {
                List<Person> teammatesName = personRepository.findByTeammatesName(p.getName());
                p.setTeammates(new HashSet<>(teammatesName));
                log.info("\t" + p.toString());
            });

验证

再次运行程序,得到正确结果:
springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)_第7张图片

你可能感兴趣的:(springboot,neo4j)