Jack Dalton Jack Dalton - 1 year ago 93
Java Question

How can I use GraphRepositories to return complex POJO's with a specified depth (currently using Neo4j templating)


I am working on a java spring web application backed by a Neo4j database. I have an object "Student" that has taken a number of "Modules" and "Courses". The relationship is connected via "rich relationship" nodes "RR_TakenModule" and "RR_TakenCourse" that specify a grade property.

public class Student extends DomainObject {
String fullName;
Gender gender;
Collection<RR_TakenModule> modulesTaken;
Collection<RR_TakenCourse> coursesTaken;
DateTime yearStarted;

that way I could ask for a Student that got 74% in a Module


I cannot return a "deep" object, from the GraphRepository set up. Ie I cannot return a Student with populated "modulesTaken" and "coursesTaken" properties. I've seen several approaches online such as trying the cypher query :

MATCH (student:Student) -[:MODULES_TAKEN]-> (rr:RR_TakenModule) -[:MODULE]-> (m:Module) RETURN student, COLLECT(rr) as modulesTaken

Which is claimed to map the RR_TakenModules into the object dynamically via the property name. It does not do this for me and returns a "Error mapping GraphModel to instance of com.domain.Actors.Student" error code. Although note that it does properly group when running the cypher query in the localhost:7474 interface. Clearly mapping is the issue.

Currently I have adopted the template and Map approach. Using Neo4jOperations and the Result object. This works, however means that I have to write out iterators that go through and assign values based on the key/value pairs in the result object. This leads to high maintenance and a larger chance of errors.

Looking around their used to be options such as @Fetch, and specifying depth in Neo4jTemplate queries, however non of these methods seem to be present in my version (most appear to be depreciated)


Is there a way to map sub-objects (ie "collection prop" and "set prop") of a Neo4j entity object via Graph Repositories.
I realise there are predefined methods such as "findOne" that have a depth parameter, but I want to apply a similar implementation to my custom queries.

Alternatively, is there a solution for dynamically mapping a Neo4jOperations Result object to a java object without defining some custom json parser




Answer Source

After looking into the default "findOne(nodeid, depth)" method GraphRepositor offers I have found a solution that works for me.

I format the query as MATCH (n:Entity) WITH n MATCH p=(n)-[*0..4]->(m) RETURN p where Entity is the name of your base entity. I cannot justify why, but this format will dynamically map the result to your respective POJO.

Note you can specify the depth (*0..4) to specify how deep a POJO is populated. It is also worth noting that the relationship is using -[]-> not -[]- which is the default relationship for findOne(nodeid, depth). If this does not work it might be possible that you have not got the latest Neo4j OGM version.