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.
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.
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.
@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.
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.
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!
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.
I also have this issue with Drupal GraphQL responses, which often includes nested "entity" objects.
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
}
}
}
Any progress with the support for aliasing nested queries just like in @acomito's use case? Is it possible? Thanks!
Waiting for it too.
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.
Most helpful comment
@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:
return
instead of
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.