How to fetch blogPosts filtered on category in Sanity.io.
Your first query is very close! The key to filtering an array of references in GROQ is using the @ operator (parent operator) to filter within the array itself. Here's how to solve your problem:
Simple approach using in:
*[_type == "blogPost" && "news" in categories[]->slug.current] {
...
}This uses the in operator to check if "news" exists in the array of dereferenced category slugs.
More flexible approach using @ (recommended):
*[_type == "blogPost" && count(categories[@->slug.current == "news"]) > 0] {
...
}The @ operator is crucial here - it refers to the current element in the array iteration. So categories[@->slug.current == "news"] means "filter the categories array to only include references where the dereferenced slug.current equals 'news'".
This pattern was demonstrated in this community answer and is particularly powerful when you need multiple conditions.
For multiple categories:
*[_type == "blogPost" && count(categories[@->slug.current in ["news", "updates"]]) > 0] {
...
}Adding more conditions (like checking if items are disabled):
*[_type == "blogPost" && count(categories[@->slug.current == "news" && !@->disabled]) > 0] {
...
}Why your original attempts didn't work:
categories[]->slug.current == "news"tries to compare the entire array result to a single value, rather than filtering within the array(categories[]->slug.current)[@ in ["news"]]has the syntax backwards - you need to filter before dereferencing
Important note: These patterns require API version v2021-03-25 or later. If you're using an older API version, you'll need to update your client configuration to use the newer API version.
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.