GraphQL is one of the most widely used query and manipulation languages for APIs. It is a great alternative to REST APIs due to various advantages. I have worked on various products that used GraphQL as a middleware; developed in TypeScript as well as Python. During those implementations, I wanted to optimize my changes for better overall performance. This article describes a use case for GraphQL info in a query resolver to achieve some of those optimizations
Prerequisites
- Understanding of web APIs and its role in a web architecture
- Understanding of GraphQL fundamentals
- Experience implementing GraphQL API in at least one programming language
info Object
GraphQL query resolver receives four parameters; obj (root or parent), args, context and info. The info object holds details related to the current query. The structure of info object is as shown below
We will be utilizing fieldNodes values from the info object in the use case below
Use case: Optimize back-end SQL queries
The most common architecture, with GraphQL as middleware, is web UI querying information from a back-end. GraphQL integrates with a database service so when the UI invokes a GraphQL query, the resolver retrieves the details from the database via SQL query and returns it to the front-end. GraphQL info in query resolver can help to optimize this SQL queries
Consider the following GraphQL schema,
type Condo {
id: ID!
Type: String
Address: String
Owner: String
Price: Float
Bedrooms: Int
Bathrooms: Float
Parking: String
YearBuilt: Int
LotSize: Int
PricePerSquareFeet: Float
WalkScore: Int
}
type Query {
condos: [Condo]
}
Code language: CSS (css)
It is a simple query to request list of condos to display on a front-end. The resolver for the query connects to a database to retrieve the list,
sql_query = 'select * from condos'
Code language: JavaScript (javascript)
Front-end can trigger the following query,
{
condos {
Address
Owner
Price
}
}
This is very simple and straightforward so far. However, if you observe closely, front-end requests only Address, Owner and Price but the SQL query retrieves all the field values for the records. This can have significant impact when you have records with large fields set; every database retrieval will include this large fields set while front-end only requires sub-set of the fields. This is where info parameter can help. If you parse the info object in the resolver and look at fieldNodes, it contains the selected fields. The screenshots below are showing info object for the above GraphQL query in Graphene
So, instead of retrieving all the database fields, the selected fields can be parsed in the resolver. This change will have a significant impact when you have a large fields set per record and GraphQL query has to return large record set to the front-end
fields = ','.join(node.name.value for node in info.field_nodes[0].selection_set.selections)
sql_query = 'select ' + fields + ' from condos'
Code language: JavaScript (javascript)
You can implement more advanced parsing logic for the fields using recursive algorithm, so that all the fields with multiple depths can be retrieved to form more advanced SQL query