When building a custom GraphQL endpoint in Magento 2, basic data fetching is just the beginning. If you’re planning to build real-world APIs, especially for storefronts or dashboards, your custom GraphQL should support filtering, sorting, and pagination.
In this tutorial, we’ll walk you through how to enhance your custom GraphQL query to support these features in Magento 2 — all with clean and maintainable code.
Add Filtering, Sorting, and Pagination GraphQL in Magento 2
🧠 Why Filtering, Sorting, and Pagination Matter
When you’re building dynamic front-ends (like Vue/React apps or headless PWAs), you’ll likely need to:
- Show a paginated list of items (e.g., 10 per page)
- Let users search or filter records (e.g., by ID, name, etc.)
- Sort the data (e.g., newest first, A–Z, etc.)
Magento 2’s GraphQL layer is powerful and flexible enough to support this natively — even in custom modules.
📦 Pre-requisites
Before starting, ensure you already have a custom GraphQL module set up. If you don’t, refer to our previous post:
👉 Create a Custom GraphQL Endpoint in Magento 2
Add Filtering, Sorting, and Pagination GraphQL in Magento 2
✅ Step 1: Define Your Schema
Update your schema.graphqls
to include filter, sort, and pagination inputs:
type Query {
getCustomRecords(
filter: CustomRecordFilterInput
sort: CustomRecordSortInput
pageSize: Int = 10
currentPage: Int = 1
): CustomRecordResult @resolver(class: "SbDevBlog\\CustomGraphQL\\Model\\Resolver\\GetRecords")
}
input CustomRecordFilterInput {
id: IntFilterInput
title: StringFilterInput
}
input CustomRecordSortInput {
title: SortEnum
id: SortEnum
}
enum SortEnum {
ASC
DESC
}
type CustomRecordResult {
items: [CustomRecord]
total_count: Int
page_info: PageInfo!
}
type PageInfo {
page_size: Int!
current_page: Int!
total_pages: Int!
}
🔧 Step 2: Update the Resolver Logic
Inside your resolver GetRecords.php
, modify your code to apply filters, sorting, and pagination using Magento’s collection methods.
public function resolve(
Field $field,
$context,
ResolveInfo $info,
array $value = null,
array $args = []
) {
$collection = $this->collectionFactory->create();
// Apply filters
if (!empty($args['filter'])) {
foreach ($args['filter'] as $field => $condition) {
foreach ($condition as $type => $value) {
$collection->addFieldToFilter($field, [$type => $value]);
}
}
}
// Apply sorting
if (!empty($args['sort'])) {
foreach ($args['sort'] as $field => $direction) {
$collection->setOrder($field, $direction);
}
}
// Pagination
$pageSize = $args['pageSize'] ?? 10;
$currentPage = $args['currentPage'] ?? 1;
$collection->setPageSize($pageSize)->setCurPage($currentPage);
// Format the response
return [
'items' => $collection->getItems(),
'total_count' => $collection->getSize(),
'page_info' => [
'page_size' => $pageSize,
'current_page' => $currentPage,
'total_pages' => ceil($collection->getSize() / $pageSize)
]
];
}
🧪 Test Example Query
query {
getCustomRecords(
filter: { title: { like: "%demo%" } }
sort: { id: DESC }
pageSize: 5
currentPage: 1
) {
items {
id
title
description
}
total_count
page_info {
page_size
current_page
total_pages
}
}
}
This will return filtered records where the title includes “demo”, sorted by ID in descending order, and paginated to 5 items per page.
🛠️ Pro Tips
- Use
like
,eq
,neq
,in
, andgt/lt
for rich filtering. - Combine multiple filters for advanced querying.
- Keep resolver logic clean by offloading filtering/sorting to a service class if it grows large.
📘 Wrapping Up – Add Filtering, Sorting, and Pagination GraphQL in Magento 2
You’ve now empowered your custom GraphQL endpoint with all the tools it needs to behave like a production-ready API. Filtering, sorting, and pagination are must-haves for scalable, performant APIs — and Magento 2 makes it pretty smooth once you understand the pattern.
✨ Next Post Preview
In the next guide, we’ll dive into creating GraphQL mutations to insert, update, and delete data in your custom table — making your Magento GraphQL truly full-stack.
🔗 Stay tuned on SB Dev Blog for more Magento magic!