Filtering nested arrays in GROQ without global scope
You're absolutely right that filtering within the context of returned arrays requires a different approach than the global *[] pattern. The key is understanding how to filter after dereferencing.
Filtering dereferenced arrays
To filter chapters based on their slug.current field after dereferencing, you can apply a filter directly to the dereferenced array:
*[_type == 'module' && slug.current == $module]{
"chapters": chapters[]->[slug.current == $chapterSlug]
}This works because:
chapters[]->dereferences all chapter references, giving you an array of chapter documents[slug.current == $chapterSlug]filters that dereferenced array based on the slug field in the actual chapter documents
According to the pipeline components documentation, the filter component [<boolean>] iterates over elements of an array and returns only those where the expression evaluates to true. The documentation notes that "this operator is actually the filter pipeline component in disguise, since it has an implicit | operator before it."
Alternative: Filter before dereferencing
If you need to filter based on properties of the reference itself (like _key or _ref), you can filter before dereferencing:
*[_type == 'module' && slug.current == $module]{
"chapters": chapters[_key == $someKey]->
}However, this won't work for filtering by fields in the referenced documents (like slug.current), since those fields don't exist on the reference object itself—they only exist in the referenced document.
Combining operations
You can chain multiple operations together on dereferenced arrays:
*[_type == 'module' && slug.current == $module]{
"chapters": chapters[]->[slug.current match $searchTerm] | order(orderRank asc)[0..4]
}This filters the dereferenced chapters, then uses the pipe operator for ordering and slicing—all within the projection scope, exactly what you're looking for! The pipe operator is required for functions like order() but the filter syntax works directly on arrays.
Show original thread20 replies
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.