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
$batch
variable 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
id
parameter 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
$batch
allows 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.