Comments (10)
And to finish: how the client is supposed to send which operation to run if there are many operations in the document ?
Up to the server; the reference implementation just has the operationName
as another parameter, so I could imagine having a HTTP Param for the operation name.
Until now I imagined graphql as a simple GraphQLQuery => Server => Response behavior. The client sending its query in string at a server endpoint. So I'm a bit disappointed by this many-operations document :-/
This is definitely the right way to think about things; a Document is just an additional concept that can contain many GraphQLQueries. If you send a document with only one query, then graphql is just QueryInDocument => Server => Response. If the document has many queries, then you specify a query so that we can go Document => Query => Server => Response
So now what wonder me is... what's the point of having a document that can contains many operations ?
The use is threefold:
- It's often useful to store GraphQL documents in a client side file; we use
.graphql
files on iOS and Android for this. We wanted the parser to work on these files as well (so the parser is universal), but you can (and we often do) include multiple queries in a single document. - One optimization that can be made (and that we'll discuss in more detail in the future, I'm sure) is "persisting" documents; you send the document to the server who stores it for you and gives you an identifier for that, that way you don't have to send the whole document string up every time. If you do that, you can send a document up with all your queries, and then pass the document ID + operation name over the wire. This would optimize bytes being sent from the client to the server.
- It's possible to write a "batch" API for GraphQL, where you use the results from one query as the parameters to another. We're still working out the exact details there, but if you do that, it's useful to specify multiple queries in a single document; you'd specify which one you wanted to run at the start and the relationships between them.
You're absolutely correct that in the model we describe (pass a string to the server, get a response back), a Document with multiple operations isn't that useful; we wanted to permit it for the reasons described above.
from graphql-spec.
Ok I understand, thank you. I understood that the executor could only handle one operation at a time but maybe it could have been called many times one operation after the other.
So now what wonder me is... what's the point of having a document that can contains many operations ?
from graphql-spec.
For example what is the expected answer for this graphql query (dumb query just for the example):
We'd describe that as a Document
at the parser layer that contains two Operation
s: LukeAndLeiaNames
and LukeAndLeiaHomePlanet
.
When executing, we need to know which Operation
to run; http://facebook.github.io/graphql/#sec-Evaluating-requests covers this in the spec and https://github.com/graphql/graphql-js/blob/master/src/executor/executor.js#L162-168 in the reference implementation.
If you only have one operation in a Document
, the common case, then it's implied to run that one. If you have more than one, you specify which operation to run in a given execution.
Hope this helps!
from graphql-spec.
@dschafer thanks for your answer but it doesn't help me a lot. I understand how it is supposed to work internally.
But, let's forget the server, consider it a black box and imagine I am a client.
If I send this document:
query LukeAndLeiaNames {
luke: human(id: "1000") {
name
}
leia: human(id: "1003") {
name
}
}
query LukeAndLeiaHomePlanet {
luke: human(id: "1000") {
homePlanet
}
leia: human(id: "1003") {
homePlanet
}
}
What do I get in response from the server?
from graphql-spec.
What do I get in response from the server?
An error. The Document
contained multiple operations and the client didn't specify which one to run. If you wanted to send that document and run one specific query, you could pass an operationName
parameter.
The spec:
To evaluate a request, the executor must have a parsed Document (as defined in the “Query Language” part of this spec) and a selected operation name to run.
The executor should find the Operation in the Document with the given operation name. If no such operation exists, the executor should throw an error. If the operation is found, then the result of evaluating the request should be the result of evaluating the operation according to the “Evaluating operations” section.
In our reference implementation, we implemented a helper where if there's only one operation in the document, it's implied that the operation name is the name of that operation (since that simplifies the common case). But you can't run multiple queries in the same request; if that's the desired behavior, a single query that combines them can be run instead. With fragments, that would become simple:
query LukeAndLeiaNames {
...LukeAndLeiaNamesFragment
}
fragment LukeAndLeiaNamesFragment on Query {
luke: human(id: "1000") {
name
}
leia: human(id: "1003") {
name
}
}
query LukeAndLeiaHomePlanet {
...LukeAndLeiaHomePlanetFragment
}
fragment LukeAndLeiaHomePlanetFragment on Query {
luke: human(id: "1000") {
homePlanet
}
leia: human(id: "1003") {
homePlanet
}
}
query LukeAndLeiaBoth {
...LukeAndLeiaHomePlanetFragment
...LukeAndLeiaNamesFragment
}
from graphql-spec.
And to finish: how the client is supposed to send which operation to run if there are many operations in the document ?
Until now I imagined graphql as a simple GraphQLQuery => Server => Response
behavior. The client sending its query in string at a server endpoint. So I'm a bit disappointed by this many-operations document :-/
from graphql-spec.
Ok thanks a lot for your answers. I started to think like that about the argument for the operation to run, and for the "storage" of queries on the server (like redis does for lua scripts).
I now have a better understanding of the whole thing and can go back to my graphql server in python.
Thanks a lot.
from graphql-spec.
Thanks for the great questions!
from graphql-spec.
@dschafer I saw this and it peaked my curiosity. Did this ever make it into the spec? I haven't been able to find it anywhere yet.
It's possible to write a "batch" API for GraphQL, where you use the results from one query as the parameters to another. We're still working out the exact details there, but if you do that, it's useful to specify multiple queries in a single document; you'd specify which one you wanted to run at the start and the relationships between them.
from graphql-spec.
There's not an official spec for Facebook's implementation as far as I know; but Hot Chocolate have great documentation around their implementation of it via the @export
directive: https://chillicream.com/docs/hotchocolate/v10/execution-engine/batching/#introduction there's also quite a long discussion here: graphql/graphql-over-http#5
from graphql-spec.
Related Issues (20)
- Redundant field aliases identical to field names
- Document Level Directives HOT 10
- Coercing Variable Values when hasValue is not true and defaultValue does NOT exist HOT 7
- Strawman: mention of non-self-describing responses
- why not allow directive on field argument ? HOT 2
- On specifying ordered vs unordered enum definitions HOT 5
- Casting Error in GraphQL C# Library HOT 2
- Is there a reason graphql floats do not support Infinity and NaN? HOT 3
- Composite types is not clearly defined HOT 1
- Unclear spec for array with fragments HOT 1
- What must be the result of executing only one fragment on a list of union or interface type? HOT 3
- Interface conditions fragments may not be used across spreads, discouraging reusability HOT 2
- Hey HOT 1
- Really
- REACT
- No validation rule exists to assert mutation/subscription operations exist in the schema HOT 5
- Internal error occurred during message handling. Please check your implementation. Error: Subscription field must return Async Iterable. Received: undefined. HOT 1
- .github/CONTRIBUTING.md
- He
- Allow empty object type _extensions_ in schema HOT 10
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from graphql-spec.