Search code examples
springspring-bootneo4jspring-data-neo4j

Spring Data neo4j access relationship from both sides


In my neo4j database, I have this

(:Song)-[:APPEARS_ON {song_nr: x}]->(:Release)

From my Spring Boot application I want to access this relationship from the song side as well as from the release side, also accessing the song number.

Song.java

@Node
public class Song {

    @Id @GeneratedValue
    private Long id;
    private String name;
    private OffsetTime length;

    @Relationship(type="APPEARS_ON", direction = Relationship.Direction.OUTGOING)
    private final List<AppearsOn> releases;

    private Song(String name, OffsetTime length, List<AppearsOn> releases) {
        this.name = name;
        this.length = length;
        this.releases = releases;
    }

    public Long getId() { return id; }

    public String getName() { return name; }

    public OffsetTime getLength() { return length; }

    public List<AppearsOn> getReleases() { return releases; }

}

AppearsOn.java

@RelationshipProperties
public class AppearsOn {

    @Id @GeneratedValue
    private Long id;
    @Property("song_nr")
    private Integer songNr;

    @TargetNode
    private Release release;

    public Long getId() {
        return id;
    }


    public Integer getSongNr() { return songNr; }

    public Release getRelease() { return release; }
}

Release.java

@Node
public class Release {

    @Id @GeneratedValue
    private Long Id;
    private String name;
    private Integer year;

    @Relationship(type = "APPEARS_ON", direction = Relationship.Direction.INCOMING)
    private final List<AppearsOnReverse> songs;

    public Release(String name, Integer year, List<AppearsOnReverse> songs) {
        this.name = name;
        this.year = year;
        this.songs = songs;
    }

    public Long getId() {
        return Id;
    }

    public String getName() {
        return name;
    }

    public Integer getYear() {
        return year;
    }

    public List<AppearsOnReverse> getSongs() { return songs; }

}

AppearsOnReverse.java

@RelationshipProperties
public class AppearsOnReverse {

    @Id @GeneratedValue
    private Long id;
    @Property("song_nr")
    private Integer songNr;

    @TargetNode
    private Song song;

    public Long getId() {
        return id;
    }


    public Integer getSongNr() {
        return songNr;
    }

    public Song getSong() {
        return song;
    }
}

When I try to query something, e.g. List<Release> allReleases = releaseRepository.findAll();

I get an exception like this:

org.neo4j.driver.exceptions.DatabaseException: Expected 
RegularSinglePlannerQuery(QueryGraph {Nodes: ['  rootNodeIds@7'], .......


Instead, got: 
RegularSinglePlannerQuery(QueryGraph {Nodes: ['  rootNodeIds@7'], .......

Is it possible to access a relationship from both sides at all, or does this break SDN?

org.neo4j.driver v4.2.7
spring-boot-starter-data-neo4j v2.5.6
spring-data-neo4j v6.1.6

Solution

  • There is nothing wrong with your mapping / model The problem is in the version of Neo4j you are using. It has a query planner bug. I do not know when it appeared but it is solved with 4.3.3 / 4.2.10 and higher.

    This combined with some needed query improvements in SDN 6.1.6 lead to the problematic constellation right now. I would suggest to manually set the Spring Data Neo4j version down to 6.1.5 if you cannot upgrade the database.