Efficient way of storing relations - SDN6

Hi, I am working on an application for storing family trees. From what I have read in a book about graph databases/neo4j is that the relationships should not be duplicated.

class Person(
    val firstName: String,
    val lastName: String,
   ) {
    @Id @GeneratedValue
    var personId: Long = -1

    @Relationship(type = "CHILD_OF")
    var parents: MutableSet<Person> = mutableSetOf()

    @Relationship(type = "PARTNER_OF")
    var partners: MutableSet<Person> = mutableSetOf()

    @Relationship(type = "PARENT_OF")
    var children: MutableSet<Person> = mutableSetOf()

For example if there exists a relation such as (a)-[PARTNER_OF]->(b) , then (b)-[PARTNER_OF]->(a) would be useless, because it can be easily queried both directions even though the relation is oriented. For example:

MATCH (p: Person) WHERE id(p) = ${personId}
RETURN p, rel, other

Using the node mapped, I get two relations

which is not optimal.

In Spring Data Neo4j documentation I wasn't able to find any way of dealing with this.
How can I map the objects properly?

You could define the relationship again with incoming direction in the entity.

@Relationship(type = "PARTNER_OF")
var partners: MutableSet<Person> = mutableSetOf()

@Relationship(value = "PARTNER_OF", direction = Direction.INCOMING)
var partnersIncoming: MutableSet<Person> = mutableSetOf() // worst naming ever

but be aware that any changes to the relationship between two persons need to be in sync.

1 Like

That's clever! Thank you!

How do you propose to pass the data to the other layers of the app? Concatenating the sets might not be an efficient thing to do...

Oops! It's querying two times the PARTNER_OF relation.

It would be best if the query was:

... OPTIONAL MATCH (n)-[__sr__:`PARTNER_OF`]-(__srn__:`Person`) ...

and not:

... OPTIONAL MATCH (n)-[__sr__:`PARTNER_OF`]->(__srn__:`Person`) ...
... OPTIONAL MATCH (n)<-[__sr__:`PARTNER_OF`]-(__srn__:`Person`) ...

Can I somehow obtain the result with my own query?

Yes, you could use of course your own query.
Best would be something like MATCH (person:Person)-[partnerOfRelation:PARTNER_OF]-(partner:Person) RETURN person, collect(partnerOfRelation), collect(partner).

You might be interested in a PlugIn being developed for genealogy. It will upload a GEDCOM into Neo4j. It also imports DNA results and has functions for genetic genealogy analytics. I'm writing the documentation now. If you send me an email, I'll communicate more about this when I get back from my current travels on Friday.


David A Stumpf, MD, PhD