neo4j-graphql-js icon indicating copy to clipboard operation
neo4j-graphql-js copied to clipboard

bug: aliases break

Open bebbi opened this issue 6 years ago • 4 comments

Bug: aliased queries break.

Aliased queries can be set up in app level queries (example) or are automatically generated when the client does query merging

Example using the schema and data used in neo4j-graphql-js:

    {
      Movie(first: 2) {
        title
        a1: actors {
          name
        }
        a2: actors(first: 1, offset: 1) {
          movies {
            title
          }
        }
      }
    }

Actual output:

    {
      "data": {
        "Movie": [
          {
            "title": "Toy Story",
            "a1": [
              {
                "name": null
              }
            ],
            "a2": [
              {
                "movies": [
                  {
                    "title": "3 Ninjas: High Noon On Mega Mountain"
                  },
                  {
                    "title": "Toy Story"
                  }
                ]
              }
            ]
          },
          {
            "title": "Jumanji",
            "a1": [
              {
                "name": null
              }
            ],
            "a2": [
              {
                "movies": [
                  {
                    "title": "Jumanji"
                  }
                ]
              }
            ]
          }
        ]
      }
    }

Expected output:

    {
      "data": {
        "Movie": [
          {
            "title": "Toy Story",
            "a1": [{
                "name": "Tom Hanks"
              }, {
                "name": " Jim Varney"
              }, {
                "name": " Don Rickles"
              }, {
              "name": " Tim Allen"
            }],
            "a2": [{
                "movies": [{
                    "title": "3 Ninjas: High Noon On Mega Mountain"
                  }, {
                    "title": "Toy Story"
                }]
            }]
          },
          {
            "title": "Jumanji",
            "a1": [{
                "name": "Robin Williams"
              }, {
                "name": " Bradley Pierce"
              }, {
                "name": " Kirsten Dunst"
              }, {
                "name": " Jonathan Hyde"
            }],
            "a2": [{
                "movies": [{
                    "title": "Jumanji"
                }]
            }]
          }
        ]
      }
    }

The names in a1 are null when they are not in the a2 selectionSet. Also, a1 loses entries because of the pagination in a2.

The resulting query is

MATCH (movie:Movie {})
RETURN movie {
  .title ,
  actors: [
    (movie)<-[:ACTED_IN]-(movie_actors:Actor) | movie_actors { .name }
  ],
  actors: [
    (movie)<-[:ACTED_IN]-(movie_actors:Actor) | movie_actors {movies: [(movie_actors)-[:ACTED_IN]->(movie_actors_movies:Movie) | movie_actors_movies { .title }] }
  ][1..2]
} AS movie SKIP 0 LIMIT 2

bebbi avatar Mar 28 '18 23:03 bebbi

Hm. It may be because this lib traverses the whole tree in one go, while aliasing happens in the graphql server realm.

So the solution needs to involve resolvers? Maybe in the query, map keys which have an alias defined in resolveInfo to their alias, and at setup time, wrap the resolvers with a schema-aware function that adds field-level resolvers as pre-processing before user defined resolvers, unaliasing the keys again per resolveInfo. Along these lines:

    Movies: {
      actors: (obj, .., resolveInfo) => obj[original_key_via_resolveInfo_alias]
    }

Not sure resolveInfo tells which alias a field is called for at a given call.

bebbi avatar Mar 29 '18 10:03 bebbi

I noticed this behavior as well. Would be great if we could get some resolution on it

creatzor avatar Oct 19 '18 02:10 creatzor

Has anyone found a workaround for this?

wangrat avatar Jun 09 '20 16:06 wangrat

https://github.com/neo4j-graphql/neo4j-graphql-js/issues/608

michaeldgraham avatar May 02 '21 04:05 michaeldgraham