Search code examples
javaneo4jspring-data-neo4jneo4j-ogmnosql

How to avoid spring data neo4j fetching parent nodes as a members of a child collection in a tree data structure?


Data model:

I have a tree structure stored in neo4j, where nodes of :Node type can be parents for nodes of the same type. tree structure

:Node nodes displayed on the right. The root of the tree (displayed in red) shares some attributes with the leafs, so there is an abstract class called AbstractNode:

public abstract class AbstractNode {
    private Long id;
    @NotEmpty
    private String code;
    @Relationship(type = "SUBTREE_OF", direction = Relationship.INCOMING)
    private Set<Node> children;

    <getters & setters omitted>
}

Class for the parent node:

public class CodeSet extends AbstractNode {
    @Relationship(type = "SUBTREE_OF", direction = Relationship.OUTGOING)
    private Application parent;

    <getters and setters omitted>
}

Class for the child node:

public class Node extends AbstractNode {
    @NotEmpty
    private String description;
    @NotEmpty
    private String type;
    @NotEmpty
    private String name;
    @NotNull
    @Relationship(type = "SUBTREE_OF", direction = Relationship.OUTGOING)
    private AbstractNode parent;

    <getters and setters omitted>
}

Service layer:

This method is used for retrieving node info to the specifies depth:

@Transactional(readOnly = true)
    public Node findById(Long id, int depth) throws EntityNotFoundException {
        Node entity = nodeRepository.findOne(id, depth);
        if (entity == null) {
        throw new EntityNotFoundException(String.format("Node %d not found", id));
        } else {
            return entity;
        }
    }

Problem: When fetching the :Node nodes, the ones that have parents of the same type has these parents at the list of children, what is obviously wrong and causes other problems. See the screenshot of a debugger for the described data set: debugger screenshot

How to resolve this?


Solution

  • With Spring Data Neo4j (SDN) when there is a combination of incoming and outgoing relationships of the same type you need to annotate both field and setter/getter of incoming relationship field, otherwise you will end up with incorrect mapping.

    This is said in the SDN documentation:

    The direction attribute on a @Relationship defaults to OUTGOING. Any fields or methods backed by an INCOMING relationship must be explicitly annotated with an INCOMING direction.

    There is also an issue/feature request created in neo4j-ogm (mapping library used in spring data neo4j 4+) about this.