cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Issue when retrieving result from Neo4JRepository

Hello, I'm having an issue with deserializing a simple query using a Neo4JRepository in an example I wrote.

PersonRepository has the following method signature:

public interface PersonRepository extends Neo4jRepository<Person, String> {
...
    @Query( "MATCH (p:Person{name: $pName})-[:LOCATED_IN]-(a:Address)" +
            "MATCH (p:Person)-[:HAS]-(w:Wealth)" +
            "MATCH (p:Person)-[s:STUDIED_IN]-(o:Organization)" +
            "RETURN p.id AS id, a AS address, w AS wealth, s AS education")
    Collection<PersonDetails> getPersonDetails(@Param("pName") String personName);

The PersonDetails result object looks like this:

@Value
public class PersonDetails {
    String id;
    Address address;
    Wealth wealth;
    Collection<StudiedIn> education;
}

Address and Wealth are entities also annotated as @Value.

StudiedIn Looks like this:

@Value
@RequiredArgsConstructor
@RelationshipProperties
public class StudiedIn {
    @Id
    @GeneratedValue
    private Long id;

    private final String degree;
    private final int year;

    @TargetNode
    private final Organization organization;
}

When I use the method, I get the following error:

2021-03-09 16:31:05.057 DEBUG 15888 --- [nio-8888-exec-3] org.springframework.data.neo4j.cypher    : Executing:
MATCH (p:Person{name : $pName})-[:LOCATED_IN]-(a:Address)MATCH (p:Person)-[:HAS]-(w:Wealth)MATCH (p:Person)-[s:STUDIED_IN]-(o:Organization)RETURN p.id AS id, a AS address, w AS wealth, s AS education
2021-03-09 16:31:05.085  WARN 15888 --- [nio-8888-exec-3] .r.s.Neo4jPersistenceExceptionTranslator : Don't know how to translate exception of type class org.springframework.data.neo4j.core.mapping.NoRootNodeMappingException
2021-03-09 16:31:05.086 DEBUG 15888 --- [nio-8888-exec-3] o.s.web.servlet.DispatcherServlet        : Failed to complete request: org.springframework.data.neo4j.core.mapping.NoRootNodeMappingException: Could not find mappable nodes or relationships inside Record<{id: "0220682345", address: node<165>, wealth: node<164>, education: relationship<292>}> for org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentEntity@6c8d8b60

Do I explicitly need to map the result with the type? I understood that was implicit because of the Repository method signature definition. Surely I'm missing something else. Could you help me with this?

8 REPLIES 8

Hello, I don't think @RelationshipProperties will apply to projection DTOs.
Can you share the Person entity as well?

Person definition is below. If RelationshipProperties won't work, how can I solve it?

@Value
@Builder
@Node("Person")
public class Person {

    @Id
    @Property("id")
    private final String id;

    @Property("name")
    private final String name;

    @Property("dateOfBirth")
    private final LocalDate dateOfBirth;


    @Relationship(type="LOCATED_IN", direction=Relationship.Direction.OUTGOING)
    private Address preferredAddress;

    @Property("gender")
    private final Gender gender;

    @Property("maritalStatus")
    private final MaritalStatus maritalStatus;

    @Builder.Default
    @Property("languages")
    private final List<String> languages = new ArrayList<>();

    @Relationship(type="HAS", direction=Relationship.Direction.OUTGOING)
    private final Wealth wealth;

    @Builder.Default
    @Relationship(type="STUDIED_IN", direction=Relationship.Direction.OUTGOING)
    private final List<StudiedIn> education = new ArrayList<>();

    @Builder.Default
    @Relationship(type="RELATIVE", direction=Relationship.Direction.OUTGOING)
    private final List<Person> relatives = new ArrayList<>();
}

@florent.biville1 I think the error might not be related with RelationshipProperties, as even removing its collection from the query and from the result object, I still get the same error:

Failed to complete request: org.springframework.data.neo4j.core.mapping.NoRootNodeMappingException: Could not find mappable nodes or relationships inside Record<{id: "0220687650", address: node<165>, wealth: node<164>}> for org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentEntity@3e63bd6b

I'm not entirely sure, but I think you can only create projections based on simple properties, not @relationship-annotated fields. I'll let @gerrit.meier confirm whether that's the problem or not.

It would/should work but the initial problem is not within the projection but the custom query.
Spring Data Neo4j does not know what it should create based on "arbitrary" values that get returned.
We have a section in the documentation about good custom query style Spring Data Neo4j .

The idea of a projection is to get a different (use-case-specific) view on the original entity. That's why some information what the underlying node/entity is is needed.

SDN would also respect the given projection definition for a derived query:

Collection<PersonDetails> findByPersonName(String personName)

This will filter the requested data for the Person to the fields you have defined in the projection class (tip: use just an interface here Spring Data Neo4j). There is currently a limitation that prevents us from also respecting the fields of nested projections but this will hopefully get resolved in the next months.

I will for sure have a look on the RelationshipProperties in projections, because right now I am really unsure what will happen there. But as I said, the problem starts earlier here.

@gerrit.meier @gnchark I have the same issue my query is very simple and the projection i am doing is following guidelines given in [Spring Data Neo4j](Spring Data Neo4J Projection) documentation.
My Code:

@Query("MATCH (User {mobile:$mobile})-[CONTACT]-(n:User)-[STEPTAKER]-(s:Step) RETURN n.name AS name s.count AS count")
public List<StepList> findAllStepByMobile(String mobile);
    

interface StepList{
    String getName();
    int getCount();
}

The error:
2021-09-10 10:36:25.180 ERROR 18088 --- [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path threw exception [Request processing failed; nested exception is org.springframework.data.neo4j.core.mapping.NoRootNodeMappingException: Could not find mappable nodes or relationships inside Record<{s.count: 400}> for org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentEntity@305b43ca] with root cause

org.springframework.data.neo4j.core.mapping.NoRootNodeMappingException: Could not find mappable nodes or relationships inside Record<{s.count: 400}> for org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentEntity@305b43ca

Hi team,

is there any solution for this issue as i have the same issue?

Thanks,

Radhakrishna.

theFrank
Node

Hi, I'm also running into the same problem.

Specifically, I have defined an interface-based projection to retrieve a view of a persisted entity from the database through a custom query. However, when I try to run the query from the backend, I get the following 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

 

Here is my custom query (inside a Neo4j Spring repository with root entity Student):

 

@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);

 

here is my StudentCandidate (the projection interface):

 

public interface StudentCandidate {

String getName();

int getAge();

String getSex();

String getOccupation();

}

 

and here's my Student class (with most details edited out for brevity's sake):

 

@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;
  }

 

as you may see, some properties (including those in the interface projection) are actually set in the Person superclass. I don't know if that's relevant.

Is there something I'm doing wrong or is this functionality not actually supported?