neo4j / graphql

A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations.
https://neo4j.com/docs/graphql-manual/current/
Apache License 2.0
511 stars 150 forks source link

Alias is not working on "wrapper" fields #5584

Open Andy2003 opened 2 months ago

Andy2003 commented 2 months ago

Its not possible to add an alias to each level of the projection.

Type definitions

type Movie {
  title: String!
  actors: [Actor!]! @relationship(type: "ACTED_IN", properties: "ActedIn", direction: IN)
}

type Actor {
  name: String!
  movies: [Movie!]! @relationship(type: "ACTED_IN", properties: "ActedIn", direction: OUT)
}

type ActedIn @relationshipProperties {
  screenTime: Int!
}

To Reproduce

Run the query

{
                movies(where: { title: "The Matrix" }) {
                    title1: title
                    actorsConnection1: actorsConnection(where: { node: { name: "Keanu Reeves" } }) {
                        edges1: edges {
                            properties1: properties {
                                screenTime1: screenTime
                            }
                            node1: node {
                                name1: name
                                b: moviesConnection(where: { node: { title: "The Matrix"}}) {
                                    edges2: edges {
                                        node2: node {
                                            title2: title
                                            a: actors {
                                                name2: name
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

Error: Cannot read properties of undefined (reading 'edges')

Additional context

Aliases are currently not supported at "wrapper" fields. I think this is a low priority bug, but since the grapqhl spec allows aliases on each field, we should support these cases as well.

angrykoala commented 2 months ago

Hi @Andy2003 Thanks for your report, I went ahead and wrote a test to validate and it seems to be working as expected. Which version of neo4j/graphql are you using?

You can check the test here to make sure I didn't misinterpreted your reproduction steps

Andy2003 commented 2 months ago

It seems to be a typing issue on my side, your test is valid and it is working as expected!

Andy2003 commented 2 months ago

But if you adjust the query to be even more fancy: you will get an error:

            query {
                ${Movie.plural}(where: { title: "The Matrix" }) {
                    title1: title
                    actorsConnection1: actorsConnection(where: { node: { name: "Keanu Reeves" } }) {
                        edges1: edges {
                            node1: node {
                                nameA1: name
                                A1: moviesConnection(where: { node: { title: "Foo" } }) {
                                    edges2: edges {
                                        node2: node {
                                            title2: title
                                            a: actors {
                                                name2: name
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        edges2: edges {
                            node1: node {
                                nameA2: name
                                A2: moviesConnection(where: { node: { title: "The Matrix" } }) {
                                    edges2: edges {
                                        node2: node {
                                            title2: title
                                            a: actors {
                                                name2: name
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

Received: [[GraphQLError: Cannot return null for non-nullable field RqZuCzQTMovieActorsConnection.edges.]]

at Object.<anonymous> (/neo4j-graphql-2/packages/graphql/tests/integration/issues/5584.int.test.ts:104:33)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
Andy2003 commented 2 months ago

I was miss-leaded by the generated cypher. There is this fallback https://github.com/neo4j/graphql/blob/28fd15ea8ed9fdb757191e9bfb91849d5ad41a1a/packages/graphql/src/schema/resolvers/field/defaultField.ts#L27 which maps fields to its alias.

But this does not work in the code I provided in the previous comment

neo4j-team-graphql commented 2 months ago

We've been able to confirm this bug using the steps to reproduce that you provided - many thanks @Andy2003! :pray: We will now prioritise the bug and address it appropriately.

angrykoala commented 2 months ago

After tinkering a bit with this. The problem is caused by the translation not applying the edge alias, meaning that it only generates 1 set of edges instead of 2. This can be replicated with a simpler query:

query {
    movies(where: { title: "The Matrix" }) {
        title1: title
        actorsConnection1: actorsConnection(where: { node: { name: "Keanu Reeves" } }) {
            edges1: edges {
                node1: node {
                    nameA1: name
                }
            }
            edges2: edges {
                node1: node {
                    nameA2: name
                }
            }
        }
    }
}