Conditionally add filter in GROQ query when reference exists
Good question! Yes, you can definitely do conditional filtering in GROQ. The issue with your original query is that when primaryCategory doesn't exist, the entire condition becomes false, filtering out those posts entirely.
There are a couple of elegant solutions:
Using coalesce() (Recommended)
The cleanest approach is using the coalesce() function, which returns the first non-null value:
*[
_type == "post" &&
slug.current == $slug &&
$primaryCategorySlug == coalesce(primaryCategory->slug.current, $primaryCategorySlug)
]This works because if primaryCategory->slug.current doesn't exist (returns null), coalesce() returns $primaryCategorySlug instead, making the comparison $primaryCategorySlug == $primaryCategorySlug, which is always true.
Using logical OR
Alternatively, you can use explicit logic with the OR operator:
*[
_type == "post" &&
slug.current == $slug &&
(!defined(primaryCategory->slug.current) ||
primaryCategory->slug.current == $primaryCategorySlug)
]This says "include the post if it doesn't have a primaryCategory OR if it does and matches the parameter."
Bidirectional check (if needed)
If you need to prevent additional path parts from being added to URLs, you might need both directions:
*[
_type == "post" &&
slug.current == $slug &&
$primaryCategorySlug == coalesce(primaryCategory->slug.current, $primaryCategorySlug) &&
primaryCategory->slug.current == coalesce($primaryCategorySlug, primaryCategory->slug.current)
]The coalesce() approach is generally cleaner and more readable once you understand how it works (it's a standard SQL function too). You can also check out GROQ conditionals for more advanced conditional logic in projections.
Show original thread10 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.