mirror of
https://github.com/vale981/apollo-server
synced 2025-03-12 05:56:40 -04:00

While the `gql` tag is not currently _required_, it does make it easier to implement additional, development-friendly functionality in the future. For example, it could avoid the need to question whether a string literal is actually using Schema Definition Language (SDL) and avoid the need to look for context clues. By implementing these suggestions now, we can avoid the need to ask developers to refactor in the future.
109 lines
3.3 KiB
Markdown
109 lines
3.3 KiB
Markdown
---
|
|
title: Fetching data
|
|
---
|
|
|
|
GraphQL is the best way to work with data from **any** back-end that your product needs. It is not a mapping of your database, but rather a graph of the data sources and shapes your product is made of. Works with multiple data sources (first party or third)
|
|
|
|
## Context
|
|
|
|
> TODO: Shorten this up, a lot.
|
|
|
|
### What is?
|
|
|
|
The `context` is the third positional argument passed to every resolver. `context` references the same object across all resolvers, so no resolver should modify the contents. Additionally, it is best to ensure that the contents of `context` does not change depending on the particular query or mutation.
|
|
|
|
The common uses of the `context` are storing [authentication scope](), database connections([mongo](), [postgres](), etc), and custom fetch functions. Additionally when batching requests across different resolvers to avoid the n+1 problem, you will attach your instances of [dataloader](best-practice) to the `context`.
|
|
|
|
|
|
> (Evans) not sure if this idea of a constant context is completely true/a best-practice, expecially if making a connection is costly, so you only start the operation if certain fields are requested
|
|
|
|
### todo: talk about state?
|
|
|
|
## How to use?
|
|
|
|
To provide a `context` to your resolvers, add an object to the Apollo Server constructor. For specific examples, follow the [backend/]() instructions.
|
|
|
|
```
|
|
const server = new ApolloServer(req => ({
|
|
typeDefs,
|
|
resolvers,
|
|
context: {
|
|
authScope: getScope(req)
|
|
}
|
|
}));
|
|
|
|
//resolver
|
|
(parent, _, context) => {
|
|
if(context.authScope !== ADMIN) throw AuthenticationError('not admin');
|
|
...
|
|
}
|
|
```
|
|
|
|
The context can also be created asynchronous, allowing database connections and other operations to complete.
|
|
|
|
```
|
|
context: async () => ({
|
|
db: await client.connect(),
|
|
})
|
|
|
|
//resolver
|
|
(parent, _, context) => {
|
|
return context.db.query('SELECT * FROM table_name');
|
|
}
|
|
```
|
|
|
|
## Implementing Queries in Apollo Server
|
|
|
|
Now that we understand the Query type, GraphQL types, and resolvers, we can explain the following code to define our schema and resolvers. This example shows the
|
|
|
|
```js
|
|
const { ApolloServer, gql } = require('apollo-server');
|
|
|
|
const typeDefs = gql`
|
|
type Process {
|
|
params: [String]
|
|
program: String
|
|
}
|
|
|
|
type Query {
|
|
process: Process
|
|
argv: [String]
|
|
}
|
|
`;
|
|
|
|
// Resolvers define the technique for fetching the types in the
|
|
// schema. We'll retrieve books from the "books" array above.
|
|
const resolvers = {
|
|
Process: {
|
|
params: (parent) => parent.argv.slice(1)
|
|
program: (parent) => parent.argv[0]
|
|
url: (_,_,context) => context.req.baseUrl
|
|
}
|
|
|
|
Query: {
|
|
process: () => process
|
|
argv: () => process.argv
|
|
},
|
|
};
|
|
|
|
new ApolloServer({ typeDefs, resolvers, context: { req } })
|
|
.listen()
|
|
.then(({ url }) => {
|
|
console.log(`Visit ${url} to run queries!`);
|
|
});
|
|
```
|
|
|
|
## Material Summary
|
|
|
|
* The context is shared by all resolvers during a single query or mutation
|
|
* setup the context on every request
|
|
* Great place to store authentication (but this will be covered in authentication)
|
|
* database connections
|
|
* mongo
|
|
* postgress
|
|
* fetch functions
|
|
* N+1 problem
|
|
* A consideration for dataloader.
|
|
* Here's how you add it to Apollo Server
|
|
* State
|
|
* BEST practice: keep your context code the same regardless of query/mutation that is coming in
|