apollo-server/docs/source/essentials/data.md

109 lines
3.6 KiB
Markdown
Raw Normal View History

2018-04-20 17:29:11 +03:00
---
2018-04-20 20:25:23 +03:00
title: Fetching data
2018-04-20 17:29:11 +03:00
---
2018-04-24 12:55:02 -04:00
## Overview
2018-04-20 20:36:32 +03:00
2018-04-24 12:55:02 -04:00
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. Resolvers are the key to this graph. Each resolver represents a single field, and can be used to fetch data from any source(s) you may have.
2018-04-20 20:36:32 +03:00
2018-04-24 12:55:02 -04:00
## Context
2018-04-20 20:36:32 +03:00
2018-04-24 12:55:02 -04:00
The context is how you access your shared connections and fetchers in resolvers to get data.
2018-04-20 20:36:32 +03:00
2018-04-24 12:55:02 -04:00
The `context` is the third argument passed to every resolver. It is useful for passing things that any resolver may need, like [authentication scope](), database connections([mongo](), [postgres](), etc), and custom fetch functions. Additionally, if you're using [dataloaders to batch requests](../best-practices/performance.html#Batching-data-lookups) across resolvers, you can attach them to the `context` as well.
2018-04-20 20:36:32 +03:00
2018-04-24 12:55:02 -04:00
As a best practice, `context` should be the same for all resolvers, no matter the particular query or mutation, and resolvers should never modify it. This ensures consistency across resolvers, and helps increase development velocity.
2018-04-20 20:36:32 +03:00
> (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
2018-04-24 12:55:02 -04:00
### How to use it
2018-04-20 20:36:32 +03:00
2018-04-24 12:55:02 -04:00
To provide a `context` to your resolvers, add a `context` object to the Apollo Server constructor. This constructor gets called with every request, so you can set the context based off the details of the request (like HTTP headers).
2018-04-20 20:36:32 +03:00
2018-04-24 12:55:02 -04:00
For specific examples, follow the [backend]() instructions.
2018-04-20 20:36:32 +03:00
```
2018-04-24 12:55:02 -04:00
const server = new ApolloServer(req => ({
typeDefs,
resolvers,
context: {
authScope: getScope(req.headers.authorization)
2018-04-20 20:36:32 +03:00
}
2018-04-24 12:55:02 -04:00
}));
// resolver
(parent, _, context) => {
if(context.authScope !== ADMIN) throw AuthenticationError('not admin');
...
}
2018-04-20 20:36:32 +03:00
```
2018-04-24 12:55:02 -04:00
The context can also be created asynchronously, allowing database connections and other operations to complete.
2018-04-20 20:36:32 +03:00
```
context: async () => ({
db: await client.connect(),
})
2018-04-24 12:55:02 -04:00
// resolver
2018-04-20 20:36:32 +03:00
(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!`);
});
```
2018-04-20 20:36:32 +03:00
## Material Summary
2018-04-24 12:55:02 -04:00
- [x] The context is shared by all resolvers during a single query or mutation
- [x] setup the context on every request
- [x] Great place to store authentication (but this will be covered in authentication)
- [ ] database connections
- [ ] mongo
- [ ] postgress
- [ ] fetch functions
- [x] N+1 problem
- [x] A consideration for dataloader.
- [x] Here's how you add it to Apollo Server
- [ ] State
- [x] BEST practice: keep your context code the same regardless of query/mutation that is coming in