Overview
Fetching nested data in GraphQL can sometimes lead to performance issues caused by the N+1 problem. Now that we understand this challenge, let's dive into solving it.
In this lesson, we will:
- Explore common patterns for batch REST endpoints and learn how to build them in Connectors
- Understand how the
$batchvariable works
Batch REST endpoints
To implement batching with Apollo Connectors, we need a REST endpoint that can handle multiple entity IDs and return data for each entity in a single response.
Here are a few common patterns for how batch REST endpoints are structured:
Repeated query parameters: Each ID is sent as a separate
idparameter in the query string.GET /resources?id=1&id=2&id=3Single query parameter with comma-separated values: All IDs are passed in a single parameter as a comma-separated list.
GET /resources?ids=1,2,3In the request body: IDs are included as filter criteria in the JSON payload.
POST /searchJSON payload: { "ids": [ 1, 2, 3 ] }
While using id is a common pattern, it's not mandatory. Other examples include upc, sku, more specific names like productId, or even composite keys.
For this course, we'll focus on the first pattern: using repeated query parameters.
Crafting URLs with query parameters in Connectors
To configure a request in a Connector that includes multiple query parameters, we use the http.queryParams property.
@connect(http: {GET: "/user"queryParams: """<KEY>: <VALUE>"""})
The queryParams property follows the same Connectors mapping language we've used before in selection. Each <KEY> represents a query parameter name, and each <VALUE> is the query parameter's value or list of values.
For example, if we need to connect to an endpoint formatted like this: http://api-example.com/user?id=1, we'll set the queryParams to include the id parameter.
type User@connect(http: {GET: "/user"queryParams: """id: $this.id"""}# ... more connect parameters) {id: ID!}
Note: Check out the Apollo documentation for other ways to build Connector URLs, including using path parameters.
$this works well for a single entity, but what if we need to handle multiple entities? That's where $batch comes in!
Introducing $batch
$batch to the rescue! The $batch variable allows us to specify that a Connector fetches data for multiple objects in a single request. It contains a list of entity references: objects representing the entities being requested using their unique identifiers. When the router encounters the $batch variable, it automatically bundles multiple requests into a single call to the batch endpoint.
Let's revisit the example of a storefront page displaying the most recent orders, where each order includes details about the customer who submitted it.
The REST API batch endpoint for requesting multiple users follows the repeated query parameters pattern: http://api-example.com/user?id=1&id=2&id=3. We can configure the request in our Connector by setting the id as the query parameter name through the http.queryParams property.
type User@connect(http: {GET: "/user"queryParams: """id: <VALUE>"""}) {id: ID!}
The value for the id query parameter needs to be an array of id values, one for each user we want to fetch. We can access those id values through the $batch variable, which contains the list of entity references for the users being requested, each containing an id property.
[{ id: 1 }, { id: 2 }, { id: 3 }]
So we'll set the value of id to $batch.id:
type User@connect(http: {GET: "/user"queryParams: """id: $batch.id"""}) {id: ID!}
With that mapping in queryParams, the Connector will automatically handle requests for multiple users, sending a single HTTP request to the batch endpoint with all requested user IDs.
This means that if the storefront page contains three orders, each one associated with user IDs 1, 2, and 3 respectively, the Connector will send a single request to http://api-example.com/user?id=1&id=2&id=3, and the response will contain data for all three users.
Practice
$batch correctly?queryParams of a Connector's request configuration define?Key takeaways
$batchallows us to combine multiple object-level requests into a single HTTP call by accessing all requested values as an array.- To use
$batch, we need a REST endpoint that accepts multiple IDs or identifiers and returns a corresponding list of results.
Up next
We now have everything we need to define a batch endpoint in a Connector and use $batch!
Share your questions and comments about this lesson
This course is currently in
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.