Search code examples
neo4jspring-data-neo4j

Why does neo4j not recognise the projection interface as the mapping type?


I'm using neo4j to store my data and am trying to retrieve only a view of some nodes to decrease data throughput. According to the official docs, this can be done through projections.

My projection interface:

public interface StudentCandidate {

String getName();

int getAge();

String getSex();

String getOccupation();

}

My query

@Repository
public interface StudentRepository extends Neo4jRepository<Student, String> {
   @Query("MATCH (students:Students)-[:LIKES]->()<-[:TEACHES]-(teacher: Teacher {email : $email})"
    + "WHERE NOT (teacher)-->(students) "
    + "RETURN DISTINCT students.name, students.age, students.sex, students.occupation")
    List<StudentCandidate> findUnmetLikingStudents(String email);

}

The persisted class (details edited out):

@Node
public class Student extends Person implements Positionable {

  @Id
  private String id;
  private double latitude;
  private double longitude;
  private int maxDistance;
  private Sex roommateSex;
  private int roommateAge;

  public Student(String username, String password, boolean enabled, boolean accountNonExpired,
      boolean credentialsNonExpired, boolean accountNonLocked, String email, String name, int age,
      String sex, String occupation, double latitude, double longitude, int maxDistance, String roommateSex, int roommateAge) {
    super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked,
        new HashSet<>(Arrays.asList(new UserAuthority(UserRole.STUDENT))), email, name, age, sex,
        occupation);
    id = UUID.randomUUID().toString();
    this.latitude = latitude;
    this.longitude = longitude;
    this.maxDistance = maxDistance;
    this.setRoommateSex(roommateSex);
    this.roommateAge = roommateAge;
  }

N.B.:

  1. some properties (including those in the interface projection) are actually set in the Person superclass (N.B. they're still called the same, i.e. "name", "age", "sex" and "occupation".
  2. "sex" and "occupation" are enumerations, not Strings, but even when I set the corresponding accessor return types in StudentCandidate to the enumerations - rather than String -, I get the same error:
org.springframework.data.neo4j.core.mapping.NoRootNodeMappingException: Could not find mappable nodes or relationships inside Record <{name: "Sara", age: 27, sex: "M", occupation: "Worker"}> for org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentEntity@30aec673

I think I'm doing everything by the book, but it looks like the driver won't see that it can map the Record to the declared return type (StudentCandidate). Does anybody have any idea why? (I've asked the same question in the Neo4j Community forum, but similar questions were asked and ignored before, so I posted it here for good measure)


Solution

  • I could be way off on this, but it looks like you are returning the data elements and the error says it is expecting nodes or relationships. Try altering your RETURN statement to

    RETURN DISTINCT students