Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alias nested fields #297

Closed
prestifidibs opened this issue Feb 18, 2016 · 19 comments
Closed

Alias nested fields #297

prestifidibs opened this issue Feb 18, 2016 · 19 comments

Comments

@prestifidibs
Copy link

Currently, you can alias fields, but only on the same level.

{
   user(id: "1") {
      identifier: id
      address {
         street
      }
   }
}

But aliasing doesn't allow you to transform the response into different forms.

{
   user(id: "1") {
      id
      street: address { street }
   }
}

This feature would be helpful in order to remove code that imperatively maps these fields and/or prevent the graphql schema from blowing up.

@leebyron
Copy link
Contributor

I'm curious to know more about your use case or what you mean when you talk about the schema blowing up.

We actually considered adding something like this quite a while ago and decided against it because it added a lot of complexity and it was clear that the few use cases we had thought of were not worth it.

For example, the query you suggest:

{
   user(id: "1") {
      id
      street: address { street }
   }
}

This is already valid GraphQL, aliasing the field address to the response name street. You would need a new kind of syntax addition to refer to deeper fields.

Secondly, this would add quite a lot of complication to the execution logic. Currently the executor only need to consider a single object when executing one selection of fields within a { }, but aliasing a field to a deeper selection would require the executor to create possibly arbitrary mappings from a response object to the internal object it reflects. This complication ends up being especially difficult when considering some of our future proposals like normalized graph-mode responses or reactive GraphQL.

I'd like to know more about what you mean by preventing a schema from blowing up. From what I understand from your proposal, this wouldn't make any alterations to the schema. You would still need to supply the full type for a "user" and for an "address". Instead this proposal just makes response formats more flexible, so a client of GraphQL could type user.street instead of user.address.street - that's flexibility was what originally caught our eye for this approach, but ultimately we decided it was not a big deal to ask clients to fully type this out in exchange for keeping the whole thing simpler.

@prestifidibs
Copy link
Author

re: my use case
Our user model currently requires you to do user.profile.displayName to get the user's name. I am implementing a dropdown that includes the user's name, and has the id as the dropdown's value. it would be nice if I could conform the user model to a { name, value } format inside of the graphql query so that I don't have to do options={users.map(user => ({ name: user.profile.displayName, value: user.id }))}, and just do options={users} in my view.

re: schema blow up
The other way I could solve this issue is by updating the graphql schema to have the displayName available on the first level of the user json, so I could do user.displayName. This would allow me to alias it easily with existing graphql functionality. However, if I changed the schema every time I wanted to format the data for my view, I would be left with a blown up schema. On top of that, I think updating the server to conform to the view is the wrong frame of mind to be in.

...ultimately we decided it was not a big deal to ask clients to fully type this out in exchange for keeping the whole thing simpler
Understood. Thanks for your response.

@junosuarez
Copy link

@leebyron I found this issue by searching for this feature, mostly to see if it was either already being considered or had been ruled out.

My use case is aliasing relay connections to be able to do something like:

{
  lastComment: comments(last: 1) {
    edges {
      node {
        body
      }
    }
  }
}

return

{
  "lastComment": {
    "body": "this is a comment"
  }
}

instead of

{
  "lastComment": {
    "edges": {
      "node": {
        "body": "this is a comment"
      }
    }
  }
}

I could achieve the same result by adding the "lastComment" alias to the schema and implement it server-side, but I'd prefer to keep this client side.

@leebyron
Copy link
Contributor

Yeah, unfortunately this could cause a host of problems.

First and foremost would be it would break Relay. Relay depends on the edge/node structure for proper pagination through connections. If that's not a feature that you use, then you're certainly free to not use the Relay style connection models. They're a trade off between robust pagination and verbosity.

Beyond anything Relay specific though, this creates a host of complexity problems for validation and execution of graphql queries. When weighing if this complexity is worth the value it produces, we've yet to see a case where true value is produced. Instead it's mostly being able to access "fooBar" instead "foo.bar" in the result, something that would be trivial for a client side transformation.

@chasingmaxwell
Copy link

I know this issue is old, but I landed on it trying to find a way to allow clients to control shape and I ended up creating graphql-leveler to make this possible. It provides the LevelerObjectType which is a drop-in replacement for GraphQLObjectType except that it adds a _get field which allows you to get any scalar value by path from the object in the resolver (a lot like lodash's get() method). Using that in combination with aliases allows clients a great deal of flexibility as to shape. There are definitely limitations, but for simple use cases like the ones mentioned above, it should work nicely. Hope it helps someone!

@conatus
Copy link

conatus commented Mar 13, 2018

We also have this use case. In general flattening deeply nested queries in a similar syntax to Javascript destructuring would be brilliant. In the use case at hand it isn't to do with edges so much, though disposing of these as we aren't using Relay would be useful...

Thanks so much.

@julkue
Copy link

julkue commented Aug 10, 2018

I also have this issue with Drupal GraphQL responses, which often includes nested "entity" objects.

@acomito
Copy link

acomito commented Aug 21, 2018

I have this use case. Would love to have one resolver that is flexible with params, then I can define one subfiled on a type, but alias it using params. Like etsy maybe could do a products resolver on a user like

query getUser() {
    getUser() {
      id
      username
      products: purchasedProducts(purchased: Boolean) {
        id
        name
      }
      products: watchedProducts(watched: Boolean) {
        id
        name
      }
        
    }
 }

@triunm
Copy link

triunm commented Oct 9, 2018

Any progress with the support for aliasing nested queries just like in @acomito's use case? Is it possible? Thanks!

@daniele-orlando
Copy link

Waiting for it too.

@dalibor-matura
Copy link

I've noticed there's also the following solution: GraphQL Lodash https://github.com/APIs-guru/graphql-lodash, but I'm not sure if it is good or not.

@0biWanKenobi
Copy link

Waiting for it too.

waiting for it, make it three

@hutber
Copy link

hutber commented Oct 28, 2021

Still waiting :D Thank you for all your work too

@jasonhibbs
Copy link

It’s my first day looking at GraphQL and I already need this

@jaycverg
Copy link

jaycverg commented Mar 6, 2022

I just got here from a google search and we also have this scenario. In our case, we are using the Hasura GraphQL server and we have a few named queries. These are queries that we expose to our client app as a RESTful endpoint. We do this because we want our client app to only consume these specific object graph structure.

If this request will be implemented, we can simplify the RESTful endpoint's response object structure by aliasing the nested fields.

The main reason we are doing this is we want to reuse our existing GraphQL server and take advantge of the RESTful facade provided by Hasura.

The client app is by design RESTful only.

I'm not sure if my comment is valid for this issue thread but I am just interested on this feature and just sharing our use case.

@nikkirs
Copy link

nikkirs commented Sep 28, 2022

We have the exact same requirement... We also want to expose the REST endpoints by flattening some of the nested fields by giving an alias name to them. Do we have any updates for this?

Example

{
 car{
   carName
   model:carModel{
     modelId
  }
 }
}

Should give a response as

{
 "car":{
    "carName":"demo_car"
    "model":"demo_model"
  }
}

@abubogale342
Copy link

abubogale342 commented Nov 22, 2022

I really need this feature. Do we have any update on this?

@cerupcat
Copy link

Would also like to see this feature. @prestifidibs any reason this is closed? Can we re-open it to get more eyes on it?

@cmaris-oyster
Copy link

I've needed this ever since I started working with GQL! Any updates?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests