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.

Querying Nodes with their relations

I want to query nodes that have a relation to eachother and return them, including the relation.
Example from the Movies dataset:

@Query("MATCH (actor:Person)-[actedIn:ACTED_IN]->(movie:Movie) WHERE ID(movie) = $movie.__id__ RETURN actor, actedIn, movie")
List<PersonActedInMovieDTO>  queryMovie(Movie movie);

If I use a DTO for this

public class ActorActedInMovieDTO {

    private Actor actor;
    private ActedIn actedIn;
    private Movie Movie;
}

I get this exception:
org.neo4j.driver.exceptions.value.NotMultiValued: RELATIONSHIP is not iterable

If I leave out the relationship the code works just fine, but then the actor object returned, does not even have its relationship attributes filled, i. e. the List attribute actedIn is empty.

Is DTO even the right way to do this? I find it very hard to understand what kind of query/mapping/projection to use for different use-cases. Generally, I want to get instances that I can work with, and write back to the database. Is it better to revert back to neo4j-OGM for this?

1 ACCEPTED SOLUTION

You would have an entity definition as shown here (with all the other ones involved like Actor, Person..) spring-data-neo4j/Movie.java at 495bd21eb530405b145bb33573b10e36f2109656 · spring-projects/spring-da...
Just a shortened version:

@Node
public final class Movie {

// id and other properties

	@Relationship(value = "ACTED_IN", direction = Direction.INCOMING)
	private List<Actor> actors;

// other things
}

With your query

MATCH (actor:Person)-[actedIn:ACTED_IN]->(movie:Movie) WHERE ID(movie) = $movie.__id__ RETURN actor, actedIn, movie

you would have to change the returned values in something like the pattern root node, list(relationships), list(related nodes). This is also described in the documentation chapter Custom queries

MATCH (actor:Person)-[actedIn:ACTED_IN]->(movie:Movie) WHERE ID(movie) = $movie.__id__ RETURN collect(actor), collect(actedIn), movie

I did this now movie-centric because it aligns better to the example entity linked above.

View solution in original post

6 REPLIES 6

Hello

What this means is that you need to connect to next iterable node from previous node and the connection is missing between 2 Nodes. It can be either thought as doubly linked list with one pointer dangling somewhere else rather than pointing to the right node. So you have not correctly embeded left referencing on right hand side and that is causing troubles in many areas. Best solution is take the dangling node and embed it in chain on Nodes that connect to the rightly referenced node. Once that is done your error will go. So you need to do apt error handling mechanism in your code to arrive at the right solution.

Thanking you
G Sameer S

Hi @sameer.gijare14,

if that's what the exception means, then there is another bug in SDN, because if I do that query on neo4j, I get exactly what I expect: Actors connected to the movie. No dangling relation ends. See the query result:

╒═════════════════════════════════════════╤═════════════════════════╤══════════════════════════════════════════════════════════════════════╕
│"actor"                                  │"actedIn"                │"movie"                                                               │
╞═════════════════════════════════════════╪═════════════════════════╪══════════════════════════════════════════════════════════════════════╡
│{"name":"Emil Eifrem","born":1978}       │{"roles":["Emil"]}       │{"tagline":"Welcome to the Real World","title":"The Matrix","released"│
│                                         │                         │:1999}                                                                │
├─────────────────────────────────────────┼─────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│{"name":"Hugo Weaving","born":1960}      │{"roles":["Agent Smith"]}│{"tagline":"Welcome to the Real World","title":"The Matrix","released"│
│                                         │                         │:1999}                                                                │
├─────────────────────────────────────────┼─────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│{"name":"Laurence Fishburne","born":1961}│{"roles":["Morpheus"]}   │{"tagline":"Welcome to the Real World","title":"The Matrix","released"│
│                                         │                         │:1999}                                                                │
├─────────────────────────────────────────┼─────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│{"name":"Carrie-Anne Moss","born":1967}  │{"roles":["Trinity"]}    │{"tagline":"Welcome to the Real World","title":"The Matrix","released"│
│                                         │                         │:1999}                                                                │
├─────────────────────────────────────────┼─────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│{"name":"Keanu Reeves","born":1964}      │{"roles":["Neo"]}        │{"tagline":"Welcome to the Real World","title":"The Matrix","released"│
│                                         │                         │:1999}                                                                │
└─────────────────────────────────────────┴─────────────────────────┴──────────────────────────────────────────────────────────────────────┘

It could be that the nodes at the end of the relation are not correctly filled. As I worte, there are no relations in the node objects I get back, when I only RETURN movie, actor.

No, this is not a bug in SDN but an intended limitation of the projection mechanism.
The DTO projection has to reflect, for example, a Movie but cannot be used as a "collector class" of arbitrary return values.
A projection is always linked to one domain entity.

Thanks @gerrit.meier. But what would be the right way to map that kind of query to objecs? As I said, I feel kind of lost to find the right type of mapping queries to objects.

You would have an entity definition as shown here (with all the other ones involved like Actor, Person..) spring-data-neo4j/Movie.java at 495bd21eb530405b145bb33573b10e36f2109656 · spring-projects/spring-da...
Just a shortened version:

@Node
public final class Movie {

// id and other properties

	@Relationship(value = "ACTED_IN", direction = Direction.INCOMING)
	private List<Actor> actors;

// other things
}

With your query

MATCH (actor:Person)-[actedIn:ACTED_IN]->(movie:Movie) WHERE ID(movie) = $movie.__id__ RETURN actor, actedIn, movie

you would have to change the returned values in something like the pattern root node, list(relationships), list(related nodes). This is also described in the documentation chapter Custom queries

MATCH (actor:Person)-[actedIn:ACTED_IN]->(movie:Movie) WHERE ID(movie) = $movie.__id__ RETURN collect(actor), collect(actedIn), movie

I did this now movie-centric because it aligns better to the example entity linked above.

Thanks @gerrit.meier - I read that part of the documentation, but did not get it. Now it's clear how that works.