4

I am modelling a very simple use case, using Spring Data Neo4j: I want to have Persons, which are connected by friendship relations. Here is my code (getters and setters are omitted here):

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

Ultimately, I make use of the following method in order to make use of my Persons:

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

In my understanding a friendship relation should be bidirectional, that is why I set its direction to (direction = Direction.BOTH). Now when executing the populateTwoPersons() method it results in the creation of the two person nodes, but not in an edge between them.

Ideas that I have tried are altering the befriend()-function to

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

or setting the direction of the relationship to direction = Direction.OUTGOING. This however creates a directed edge, which is not what I want.

Why don't I get an edge in the first case altogether? Any ideas? :)

Thanks in advance, Manu

manu
  • 43
  • 4
  • The empty hashset of the other person overrides the relationships of the current one. Set it to null or only save person1. Relationships in Neo4j are always directed. – Michael Hunger Jan 29 '15 at 02:09

2 Answers2

4

All Neo4j edges must be directed and they cannot be bi-directional. You can either create the friendship one-way and query it without direction. Or you can create two separate edges between the two friends. I think the latter is more flexible as one person may consider the other a friend but not vice versa.

Dave Bennett
  • 10,996
  • 3
  • 30
  • 41
  • 2
    Good answer. Directed edges don't have to be treated as such, you can always think of them as undirected and it's fine. Whether 2 relationships (both directed) or 1? I would suggest it depends on metadata needs. If the relationships are actually unique and not mutual (i.e. I follow Bob but he doesn't follow me) then 2 edges. If the edges aren't unique, it's better just to have one rather than using 2 just for the sake of having it be "directed both ways" – FrobberOfBits Jan 28 '15 at 22:30
  • 1
    saving it directed and querying with "-" instead of "<-" or "->" does the work, thanks – Daniel Jeney Jan 22 '21 at 10:14
2

If you don’t care about the direction then you can specify direction=Relationship.UNDIRECTED which will guarantee that the path between two node entities is navigable from either side.

For example, consider the PARTNER_OF relationship between two companies, where

(A)-[:PARTNER_OF]→(B) implies (B)-[:PARTNER_OF]→(A)

The direction of the relationship does not matter; only the fact that a PARTNER_OF relationship exists between these two companies is of importance. Hence an UNDIRECTED relationship is the correct choice, ensuring that there is only one relationship of this type between two partners and navigating between them from either entity is possible.

Source: Good Relationships: The Spring Data Neo4j Guide Book.

Poliakoff
  • 1,592
  • 1
  • 21
  • 40