Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
05 Aug 2025 · 5 min read ·Article 36 / 125
Go

36 Adding Filters to a GraphQL Query

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

36 Adding Filters to a GraphQL Query: From Concept to Implementation

In modern application development, flexibility in data retrieval is one of the key factors that keeps our backend powerful and scalable. One of GraphQL’s main advantages over REST is its ability to let clients define exactly the data structure they need. However, adding filters to a query is often a challenge. How do you implement effective filtering in a GraphQL query? This article covers the topic in full — from the concept, code examples, and simulations to best practices you can adopt in production.


What Are Filters in a GraphQL Query?

Put simply, filters in a GraphQL query allow clients to retrieve a subset of data based on certain conditions — similar to WHERE in SQL or filtering through REST query params (?name=foo). With filters, the front-end client can request more specific data without over-fetching or under-fetching.


Why Do You Need Filters in GraphQL?

Imagine you are building the backend for a book catalog application. Without filters, the frontend only has two options: fetch all the books and filter them on the client side (inefficient), or create a new backend query for every filtering requirement (not scalable).

With a filtering feature, a single GraphQL endpoint can handle a wide range of query needs — making it more reusable, maintainable, and scalable.


Case Study: A Book Catalog System

Let’s assume we have a Book data type like the following:

graphql
1type Book {
2  id: ID!
3  title: String!
4  author: String!
5  genre: String!
6  publishedYear: Int!
7}

The client needs search features such as:

  • Filter by author
  • Filter by genre
  • Filter by published-year range
  • Combining multiple filters

Building a GraphQL Filter Query

1. Define an Input Type for the Filter

The most standard approach is to define an input object called BookFilter:

graphql
1input BookFilter {
2  author: String
3  genre: String
4  publishedYearGte: Int
5  publishedYearLte: Int
6}

Use explicit field names such as Gte (Greater than or equal) and Lte (Less than or equal) for numeric filters.

2. Modify the Query in the GraphQL Schema

graphql
1type Query {
2  books(filter: BookFilter): [Book]
3}

Now the books query can accept a single optional filter parameter.


3. Implementation in the Resolver

Example implementation (pseudocode/TypeScript):

typescript
 1const books = [
 2  { id: 1, title: 'Clean Code', author: 'Robert C. Martin', genre: 'Programming', publishedYear: 2008 },
 3  { id: 2, title: 'Atomic Habits', author: 'James Clear', genre: 'Self-Development', publishedYear: 2018 },
 4  { id: 3, title: 'Eloquent JavaScript', author: 'Marijn Haverbeke', genre: 'Programming', publishedYear: 2014 },
 5  // ... and so on
 6];
 7
 8// Resolver for books
 9const resolvers = {
10  Query: {
11    books: (_parent, args) => {
12      let result = books;
13      if (args.filter) {
14        if (args.filter.author) {
15          result = result.filter(book => book.author === args.filter.author);
16        }
17        if (args.filter.genre) {
18          result = result.filter(book => book.genre === args.filter.genre);
19        }
20        if (args.filter.publishedYearGte !== undefined) {
21          result = result.filter(book => book.publishedYear >= args.filter.publishedYearGte);
22        }
23        if (args.filter.publishedYearLte !== undefined) {
24          result = result.filter(book => book.publishedYear <= args.filter.publishedYearLte);
25        }
26      }
27      return result;
28    }
29  }
30};

Simulating the Query and Response

Query

graphql
1query {
2  books(filter: { author: "Robert C. Martin", genre: "Programming", publishedYearGte: 2000 }) {
3    id
4    title
5  }
6}

Response

json
 1{
 2  "data": {
 3    "books": [
 4      {
 5        "id": "1",
 6        "title": "Clean Code"
 7      }
 8    ]
 9  }
10}

Filtering Flow Diagram

Using Mermaid, here is a simple flow for filtering in a GraphQL query:

MERMAID
flowchart TD
    A[Client Request] --> B[GraphQL Layer]
    B --> C{Ada Filter?}
    C -- Ya --> D[Filter data berdasarkan input]
    C -- Tidak --> E[Ambil Semua Data]
    D & E --> F[Return ke Client]

Example Table Simulation

Suppose the book data is as follows:

idtitleauthorgenrepublishedYear
1Clean CodeRobert C. MartinProgramming2008
2Atomic HabitsJames ClearSelf-Development2018
3Eloquent JavaScriptMarijn HaverbekeProgramming2014
4The Pragmatic ProgrammerAndy HuntProgramming1999

Given this query:

graphql
1books(filter: { genre: "Programming", publishedYearGte: 2000 })
The result would be:

idtitle
1Clean Code
3Eloquent JavaScript

Tips and Best Practices for GraphQL Filtering

  1. Use an Input Object, Not Flat Args
    An input object scales better as the number of filter fields grows.

  2. Avoid Over-Nesting
    Unless your needs are highly complex, keep nesting minimal so the schema stays easy to understand.

  3. Use Clear Data Types
    Use the right data types (String, Int, etc.) so that filtering is robust.

  4. Paging + Filtering
    It’s best to combine filtering with pagination (offset/limit or cursor-based) so queries stay fast on large datasets.

  5. Validation and Sanitization
    Always validate filter input so it can’t be exploited (for example, SQL injection).


Advanced: Supporting OR/AND or More Complex Comparators

The pattern above is basic. For more complex scenarios (such as combinations of OR, AND, NOT), you can use a nested input object and operator enums.

graphql
1input BookFilter {
2  AND: [BookFilter!]
3  OR: [BookFilter!]
4  author: String
5  genre: String
6}

Query Example:

graphql
1books(filter: {
2  OR: [
3    { genre: "Programming" },
4    { author: "James Clear" }
5  ]
6})
Filtering like this is extremely powerful for dynamic search use cases.


Conclusion

Adding filters to a GraphQL query is the foundation for building a flexible and scalable API. With modular filters, the frontend can perform highly specific searches and data retrieval without adding new backend endpoints. The steps we’ve covered — from defining the input and implementing the resolver to simulating the query — are very easy to adopt. From there, you simply scale them to fit your project’s needs.

Keep exploring and optimizing this filter schema to match your domain’s requirements — and always prioritize both performance and security!

Feel free to leave your thoughts or questions in the comments below 👇 — or share your own experience implementing filters in your products!

Related Articles

💬 Comments