0

I have the following (Project, User, Task) domain objects. How can I fetch entity with specific related objects via Spring Data Neo4j 4 (SDN4)? For example I want to fetch a project with related tasks, but without users. This sample doesn't work. Defining depth in neo4jTemplate.load method is not appropriate for me, because it gets user objects.

public Project findProjectWithTasks(Long projectId){
    Project project = neo4jTemplate.load(Project.class, projectId, 0);
    /*
        project.id      <- correct
        project.name    <- correct
        project.tasks   <- null, but in previous versions of Spring Data Neo4j I had empty entities with id 
    */

    Collection<Task> tasks = neo4jTemplate.loadAll(project.getTasks()); // <- returns null, because project.getTasks() is null 

    return project;
}

//----------

@NodeEntity
class Project {
    @GraphId
    private Long id;

    private String name;

    @Relationship(direction = Relationship.OUTGOING, type = "PROJECT_TASK")
    private Set<Task> tasks;

    @Relationship(direction = Relationship.OUTGOING, type = "PROJECT_USER")
    private Set<User> users;
}

@NodeEntity
class Task {
    @GraphId
    private Long id;

    private String name;

    @Relationship(direction = Relationship.INCOMING, type = "PROJECT_TASK")
    private Project project;

    @Relationship(direction = Relationship.OUTGOING, type = "TASK_USER_ASSIGNED")
    private User assignedTo;
}

@NodeEntity
class User {

    @GraphId
    private Long id;

    private String email;

    @Relationship(direction = Relationship.INCOMING, type = "TASK_USER_ASSIGNED")
    private Set<Task> tasks;

    @Relationship(direction = Relationship.INCOMING, type = "PROJECT_USER")
    private Set<Project> projects;
}
Luanne
  • 19,145
  • 1
  • 39
  • 51
Ibraim
  • 1
  • 1
  • 1

3 Answers3

1

You can use Neo4jTemplate.query and a custom Query to retrieve the Result. In this case n will be a Project that's been populated with properties and the Tasks. The ID function gets you the id of a node.

public Project findProjectWithTasks(Long projectId){
    String query = "MATCH (n:Project)-[r:PROJECT_TASK]->(m) WHERE ID(n) = {id} RETURN n,r,m";
    Map<String,Object> map = new HashMap<>();
    map.put(id,projectId);
    Result result =  neo4jTemplate.query(query,map);
    return (Project) result.iterator().next().get("n");
}
fkorn
  • 50
  • 6
1

SDN 4 does not support loading entities with some relations- it is none (depth 0) or all (depth n, default depth 1).

So if you load a Project with the default depth 1, it will load properties of the Project, properties of related tasks and users, but not their relationships.

If you require entity ID's only, then as answered by @fkorn, a custom query is the way to go

Luanne
  • 19,145
  • 1
  • 39
  • 51
  • can I load a certain attribute using SDN5 or there is no other way ? https://stackoverflow.com/questions/49814386/always-loading-certain-child-object-in-neo4j here is the detail question please have a look – Abdullah Al Noman Apr 13 '18 at 14:40
0

You can also used Repository and achieve the same result with @Query annotations

import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;


public interface ProjectRepository extends Neo4jRepository<Project, Long>{

  @Query("MATCH (n:Project) " +
      "WHERE ID(n) = {0} " +
      "WITH n " +
      "MATCH p=(n)-[:PROJECT_TASK*0..1]-(m:Task) RETURN p")
   public Project findProjectWithTasks(long projectId);
}
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Paulin Amougou
  • 139
  • 1
  • 10