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

Use ancestors as field arguments #144

Closed
lucaslorentz opened this issue Feb 15, 2016 · 7 comments
Closed

Use ancestors as field arguments #144

lucaslorentz opened this issue Feb 15, 2016 · 7 comments

Comments

@lucaslorentz
Copy link

Considering the following schema:

Event {
  id: String
  name: String
  speakers: [Speaker]
  talks: [Talk]
}
Speaker {
  id: String
  name: String
  events: [Event]
  talks: [Talk]
}
Talk {
  name: String
  speaker: Speaker
  event: Event
}

I would like to create queries like:

query {
   events {
     name
     speakers {
        name,
        talks {
          name
        }
     }
   }
}

I checked the specs and didn't find any way to filter the speaker's talks by the ancestor event.

I'm using directives on the examples below to demonstrate a feature GraphQL could have:

query {
   events {
     id @into (variable: "$eventId")
     name
     speakers {
        name,
        talks(eventId: $eventId) {
          name
        }
     }
   }
}

That would allow us to completely re-shape the query using the same schema:

query {
   speakers {
     id @into (variable: "$speakerId")
     name
     events {
        name,
        talks(speakerId: $speakerId) {
          id,
          name
        }
     }
   }
}

Or even go further:

query {
   events {
     id @into (variable: "$eventId")
     name
     speakers {
        name,
        talksOnThisEvent: talks(eventId: $eventId) {
          name
        },
        talksOnOtherEvents: talks(excludeEventId: $eventId) {
          name,
          event: {
            name
          }
        }
     }
   }
}

I believe such feature is a nice to have and would decouple even more GraphQL consumers, giving them the ability to completely re-group the data using any entry point: Event, Speaker

Any suggestions/opinions about that?

Related to: #88

@dylanahsmith
Copy link
Contributor

It looks like your schema already supports this type of query, which you could write as

query {
   events {
     name
     talks {
       name
       speaker {
        name
       }
     }
   }
}

@leebyron
Copy link
Collaborator

Interesting! We've been kicking around a similar idea at FB for a while for running two related queries, but doing so within a single query is new.

Typically, we try to design our type systems to avoid context-sensitive requests like this in favor of context-free requests.

For example, in your first example, you want to know all of the talks at a given event and the speakers for them, excluding talks that are not relevant to the original event. So your query:

query {
   events {
     id @into (variable: "$eventId")
     name
     speakers {
        name,
        talks(eventId: $eventId) {
          name
        }
     }
   }
}

should be re-writable as:

query {
  events {
    id
    name
    talks {
      name,
      speakers {  
        name
      }
    }
  }
}

In general, the tradeoff we struggle with when considering suggestions like this is if there are compelling use cases that cannot be reasonably solved in other ways that are worth the expense of adding additional complication to GraphQL. While it may not seem like a complicated suggestion, I can already think of a lot of edge cases that could add a ton of complication to the validator and executor.

@lucaslorentz
Copy link
Author

@dylanahsmith @leebyron
Indeed, we can rewrite the query and retrieve the correct data.

I was thinking about GraphQL as a way to query a data source in the format I want to use on the view.

If I have a view that list events, with speakers and then talks, I would prefer to don't transform data on client-side.

I opened the issue to see how everyone is handling it.
It seems that most people create schemas, based on the view needs.

@leebyron Please, evaluate and fell free to close the issue

@He-Pin
Copy link

He-Pin commented Mar 31, 2016

@lucaslorentz I have the same request now,and I just see your issue,you are trying to archive this via directive @into/@bind,I was thinking about introduce a $$ and for a scope reference like a.b.c.

currently,there is no much tools around there,so we my need some adoption for the specified use case.

@lucaslorentz
Copy link
Author

@hepin1989
$$ is a nice syntax. We need to be able to go up on scope and then pick the path we want.
Maybe introducing a $$parent and $$parents[n] variables:

query {
   events {
     id
     name
     speakers {
        name,
        talks(eventId: $$parent.id) {
          name
        }
     }
   }
}

Anyway, there is a need to use data from query results inside the same query.

@He-Pin
Copy link

He-Pin commented Apr 9, 2016

@lucaslorentz we at taobao are currently using graphql to build our next generation content platform too,we need some context value to generate the final result.
I think we could make use of super/parent.${parameterName} to fetch the data from it's source object.
and we could make use of the this.${parameterName} to fetch the data from it's currently context too.
Both case is make it as a variable.

We currently make use of both,but we have not change the syntax but how to fill the $variable.

@lucaslorentz
Copy link
Author

For now you have the following options:

  • Create custom directives and implement that feature on your graphql server.
  • Adapt the query, changing the root entrypoint like @leebyron suggested, and later transform data on front-end to the shape you want.

Closing it.

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

4 participants