Querying for specific categories and subcategories in Sanity.io
I see you're trying to get all posts related to a specific category and its subcategories in one query. This is a common challenge with hierarchical data in Sanity!
The issue is that GROQ doesn't have built-in recursive queries, so you need to handle the hierarchy manually. Here are a couple of approaches:
Approach 1: Two-step query with subcategory IDs
First, fetch the parent category and collect all its subcategory IDs, then use those to filter posts:
*[_type == "blogPostTag" && key.current == "digital-marketing"][0]{
_id,
title,
"subcategoryIds": [_id] + *[_type == "blogPostTag" && references(^._id)]._id,
"posts": *[_type == "localizedBlogPostEntry" && count((tags[]->_id)[@ in ^.subcategoryIds]) > 0]
}This query:
- Gets your parent category
- Creates an array of IDs including the parent (
_id) and all subcategories that reference it - Filters posts where any of their tags match those IDs
Approach 2: Using a subquery in the filter
You can also inline the subcategory lookup directly in the posts filter:
*[_type == "blogPostTag" && key.current == "digital-marketing"][0]{
_id,
title,
"posts": *[_type == "localizedBlogPostEntry" && (
references(^._id) ||
count((tags[]->_id)[@ in *[_type == "blogPostTag" && references(^._id)]._id]) > 0
)]
}This checks if posts reference either the parent category directly OR any of its subcategories.
Important notes:
- Since your schema has
parentCategoryas a reference field on subcategories pointing to parents, you're querying "bottom-up" (subcategories reference parents) - The
references()function checks if a document references another, which works perfectly for your use case - The
count()and array filtering syntax[@ in array]lets you check if any tag matches your subcategory list
The key insight from the reference fields documentation is that references are bidirectional when queried, so you can traverse them from either direction even though the reference field only appears in the Studio where it's defined.
If you need to go deeper than one level (subcategories of subcategories), you'd need to either flatten your data structure or handle multiple levels explicitly in your query, as GROQ doesn't support recursive traversal natively.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.