Creating a Neo4J node with multiple relationships and bi-directional relationships

56 views Asked by At

I'm trying to do the following: Create Person and Dog nodes which have the following relationships: Person has 2 relationships: TEAMMATE with a list of Persons and 'OWNER_OF' with a list of dogs

Dog has 1 relationship: OWNED_BY with a single person

So for example: I have 2 people: Chris and Roger. Roger is a teammate of Chris and 1 dog: Ghost which is owned by Chris

My endgame is to query the following: get me all the teammates of a person who is the owner of a dog named Ghost (the result is Roger from the example)

I created the following code:

@Node
data class Dog(
        @Id @GeneratedValue
        val id: Long?,
        val name: String,
        @Relationship(type = "OWNED_BY")
        var owner: Person? = null) {
    constructor(name: String) : this(null, name)

    override fun toString(): String {
        return "$name's owner => ${owner?.name}"
    }

    override fun hashCode(): Int {
        return id?.hashCode() ?: super.hashCode()
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as Dog

        if (id != other.id) return false
        return name == other.name
    }
}

@Node
data class Person(
        @Id @GeneratedValue
        val id: Long?,
        val name: String,
        @Relationship(type = "TEAMMATE")
        var teammates: MutableSet<Person> = mutableSetOf(),
        @Relationship(type = "OWNER_OF")
        var dogs: MutableSet<Dog> = mutableSetOf()) {

    constructor(name: String) : this(null, name)

    fun addTeammates(person: Set<Person>) {
        teammates.addAll(person)
    }

    fun addDog(dogs: Set<Dog>) {
        this.dogs.addAll(dogs)
    }

    override fun toString(): String {
        val teammatesList = teammates.stream().map(Person::name).toList()
        val dogsList = dogs.stream().map(Dog::name).toList()
        return "$name's teammates => $teammatesList, dogs => $dogsList"
    }

    override fun hashCode(): Int {
        return id?.hashCode() ?: super.hashCode()
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as Person

        if (id != other.id) return false
        return name == other.name
    }
}

@Repository
interface DogRepository : Neo4jRepository<Dog, Long>
@Repository
interface PersonRepository : Neo4jRepository<Person, Long>

I'm creating the following demo:

    @PostMapping("/demo2")
    fun addDemo2() {
        // Delete existing data (optional)
        personRepository.deleteAll()
        dogRepository.deleteAll()

        val chris = Person("Chris")
        val roger = Person("Roger")
        val ghost = Dog("Ghost")

        // Establish the relationships manually
        ghost.owner = chris
        chris.dogs.add(ghost)
        chris.addTeammates(setOf(roger))

        // Save the entities
        personRepository.save(chris)
        dogRepository.save(ghost)
    }
}

when I run this, I'm getting the following error:

java.util.NoSuchElementException: No value present
    at java.base/java.util.Optional.orElseThrow(Optional.java:377) ~[na:na]
    at org.springframework.data.neo4j.core.TemplateSupport.retrieveOrSetRelatedId(TemplateSupport.java:412) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
    at org.springframework.data.neo4j.core.Neo4jTemplate.lambda$processNestedRelations$28(Neo4jTemplate.java:839) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
    at org.springframework.data.neo4j.core.mapping.AssociationHandlerSupport.lambda$doWithAssociations$0(AssociationHandlerSupport.java:51) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
    at org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:317) ~[spring-data-commons-3.1.5.jar:3.1.5]
    at org.springframework.data.neo4j.core.mapping.AssociationHandlerSupport.doWithAssociations(AssociationHandlerSupport.java:49) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
    at org.springframework.data.neo4j.core.Neo4jTemplate.processNestedRelations(Neo4jTemplate.java:731) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
....

Any idea?

0

There are 0 answers