如何在Spring Data Neo4j中实现双向关系?

4

我正在建模一个非常简单的用例,使用Spring Data Neo4j:我想拥有人员,这些人员通过友谊关系相互连接。这是我的代码(此处省略了getter和setter):

@NodeEntity
public class Person {
    @GraphId
    private Long id;
    private String name;
    private String password;

    @RelatedTo(type = "FRIEND_OF", direction = Direction.BOTH)
    private Set<Person> friends = new HashSet<Person>();

    public Person() {};

    public Person(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public void befriend(Person person) {
        this.friends.add(person);
    }

最终,我使用以下方法来利用我的人员:
@Transactional
private void populateTwoPersons() {
    Person person1 = new Person("Alice", "pw1");
    Person person2 = new Person("Bob", "pw2");

    List<Person> persons = Arrays.asList(person1, person2);
    personRepository.save(persons);

    person1.befriend(person2);

    personRepository.save(persons);
}

在我看来,友谊关系应该是双向的,这就是为什么我将其方向设置为(direction = Direction.BOTH)。现在,在执行populateTwoPersons()方法时,会创建两个人节点,但它们之间没有边缘。

我尝试过的想法是修改befriend()函数为

public void befriend(Person person) {
    this.friends.add(person);
    person.getFriends().add(this);
}

或者将关系的方向设置为direction=Direction.OUTGOING。然而,这会创建一个有向边,这不是我想要的。

为什么在第一种情况下我根本没有得到一条边呢?有什么想法吗?:)

提前感谢, Manu


另一个人的空哈希集会覆盖当前人的关系。将其设置为null或仅保存person1。Neo4j中的关系始终是有向的。 - Michael Hunger
2个回答

5

所有Neo4j的边必须是有向的,不能是双向的。你可以创建单向的友谊关系,并在查询时不考虑方向。或者你可以在两个朋友之间创建两条独立的边。我认为后者更灵活,因为一个人可能会认为另一个人是朋友,但反过来不一定成立。


2
好的回答。有向边不一定要被视为有向的,你可以始终将它们视为无向的,这样也没问题。关于两个关系(都是有向的)还是一个?我建议这取决于元数据需求。如果这些关系实际上是唯一的而且不是相互的(例如,我关注Bob,但他不关注我),那么就需要2条边。如果这些边不是唯一的,最好只使用一条边,而不是仅仅为了让它成为“双向的”。 - FrobberOfBits
1
将其保存并使用“-”而不是“<-”或“->”进行查询即可完成,谢谢。 - Daniel Jeney

2
如果您不关心方向,可以指定direction=Relationship.UNDIRECTED,这将确保两个节点实体之间的路径可以从任一方向导航。
例如,考虑两个公司之间的PARTNER_OF关系。
(A)-[:PARTNER_OF]→(B) implies (B)-[:PARTNER_OF]→(A)

关系的方向并不重要,只有这两家公司之间存在PARTNER_OF关系才是重要的。因此,选择一个UNDIRECTED关系是正确的选择,确保在两个合作伙伴之间只有一种这种类型的关系,并且可以从任何实体导航到另一个实体。
来源:好的关系:Spring Data Neo4j指南

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接