Fetching multiple document types with conditional fields in Sanity GROQ query
I can see the issue with your query! The syntax you're using isn't quite right for conditional projections in GROQ. You're trying to use _type == 'event': { ... } as if it's creating conditional objects, but that's not valid GROQ syntax.
Here's the correct approach using conditional projections with the => operator:
*[_type in ['event', 'calendar', 'notice']]{
_type,
_type == 'event' => {
eventTitle,
eventDate,
venue,
mainImage,
artists[]->
},
_type == 'notice' => {
_id,
title,
body
},
_type == 'calendar' => {
_id,
month,
'event': event[]->{
title,
date
}
}
}Key differences:
- Use
=>instead of:- The arrow operator (=>) is what makes conditional projections work in GROQ - Include
_typein the base projection - This helps you identify which type each document is when you process the results in Next.js - Remove the curly braces around conditions - Each condition should be at the projection level, not wrapped in an object
The way this works: when _type == 'event' is true, those fields get included in the projection. When it's false, they're simply omitted. Each document in your results will only have the fields relevant to its type.
If you want to include common fields for all types plus type-specific ones, you can use the ellipsis operator:
*[_type in ['event', 'calendar', 'notice']]{
...,
_type == 'event' => {
artists[]->
}
}This would include all existing fields from each document, plus expand the artists reference only for event documents. The ellipsis (...) is always evaluated first regardless of position, so it won't override your conditional fields.
Show original thread7 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.