graphql icon indicating copy to clipboard operation
graphql copied to clipboard

Using optimized cypher query when using filtering on relations

Open Andy2003 opened this issue 3 years ago • 0 comments

Given the schema the schema

type Movie {
    id: ID
    title: String
    actorCount: Int
    genres: [Genre] @relation(name: "IN_GENRE", direction: OUT)
}
type Genre {
  name: String
  movies: [Movie] @relation(name: "IN_GENRE", direction: IN)
}

and the query:

{
    movie(where: { genres: { name: "some genre" } }) {
        actorCount
    }
}

this library is currently generating the following cypher:

MATCH (this:Movie)
WHERE EXISTS((this)-[:IN_GENRE]->(:Genre)) AND ALL(this_genres IN [(this)-[:IN_GENRE]->(this_genres:Genre) | this_genres] WHERE this_genres.name = $this_genres_name)
RETURN this { .actorCount } as this

The java version would instead generate:

MATCH (movie:Movie)
WHERE all(whereMovieGenreCond IN [(movie)-[:IN_GENRE]->(whereMovieGenre:Genre) | whereMovieGenre.name = $whereMovieGenreName] WHERE whereMovieGenreCond) RETURN movie { .actorCount } AS movie

According to @jexp:

Ours [The java version] is better as the planner is able to pull the condition into the expansion and doesn't have to build up a full list and post-filter

see also: https://github.com/neo4j-graphql/neo4j-graphql-java/pull/220#discussion_r624677405

btw. in a further step we will migrate to subqueries, to improve the usage of the planner

Andy2003 avatar May 04 '21 15:05 Andy2003