Neo4j Spring 数据设计

问题描述 投票:0回答:1

我目前正在开始使用 Neo4j,我想创建一个基本的社交媒体(例如应用程序)来了解更多信息。

我正在使用 spring data neo4j 将我的 Spring Boot 后端与 Neo4j 连接。

我的应用程序非常简单,它只是让一个用户关注另一个用户。

使用 Cypher 查询,一切都非常简单。但我不想显式地编写任何查询并使用存储库来获取我想要的数据。

这是我的用户类

    @Node
    public class User {
    @Id
    private Long id;
    private String name;

    @Relationship(type="FOLLOWS", direction = Relationship.Direction.INCOMING)
    private HashSet<User> followsReceived = new HashSet<>();

    @Relationship(type="FOLLOWS", direction = Relationship.Direction.OUTGOING)
    private HashSet<User> followsGiven = new HashSet<>();
}

这是我的关注课程

@RelationshipProperties
public class Follow {
    @Id @GeneratedValue
    private Long id;

    @TargetNode
    private User endNode;
}

这个设计有意义吗?

我现在有点困惑,因为例如,如果我想找到特定用户关注的用户,我会得到一个递归结构,尽管实现了分页,但它几乎加载了整个数据库。

有人可以建议我一个更简洁的设计,其中让我关注的用户和关注我的用户不会加载整个数据库。

如果可能的话,我想在没有@Query注释的情况下实现它。

java spring-boot neo4j spring-data-neo4j
1个回答
0
投票

首先,不需要

@RelationshipProeprties
类,也不需要在您的示例中使用。您必须将其作为泛型类型放入
User's
关系定义中。但由于您没有向其中添加任何属性,因此您可能 (*) 会跳过它。

关于您的主要问题:Spring Data Neo4j 默认加载从域模型角度可访问的所有内容。

User
User
之间的这种循环依赖(这在您正在工作的领域中有意义)预计会在这种情况下结束。 旧版本的 SDN 在获取数据时创建了 2 跳的虚拟屏障(如果没有参数化以加载更多数据)。 在较新的版本中,SDN 提升了预测概念,以更细粒度地定义这些障碍。 (https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#projections.interfaces

考虑到加载

User
以及她/他的所有关注者的用例,您可能会考虑定义一个像

这样的投影
interface UserProjection {
 String getName();
 Set<Follower> getFollowsReceived();
 Set<Follower> getFollowsGiven();
}

interface Follower {
 String getName();
 // no relationships defined here to break the circle
}

并在存储库中使用它,如下所示:

interface UserRepository extends Neo4jRepository<User, Long> {
  UserProjection findByName(String name);
}

(从我的脑海中写下,请查看链接的文档以了解更多详细信息)

这里重要的一点是,您仅指“根”投影 (

Follower
) 内的另一个投影接口 (
UserProjection
)。 如果您引用任何定义的实体(
@Node
注释),SDN将退回到循环加载机制以再次找到可到达的所有内容。

* 对标识符进行包装可以为您带来性能优势,因为 Spring Data Neo4j 使用此信息来确定数据库中是否已存在关系。但为此,您必须在您的

Sets
中使用它,而不是与其他
Users
的直接关系。

© www.soinside.com 2019 - 2024. All rights reserved.