Filtering an array of linked events based on date in a Groq query
You can definitely do this in GROQ! The key is to filter the array after dereferencing. You'll want to use a projection with array filtering syntax on the dereferenced objects.
Here's how to structure your query:
*[_type == 'page'] {
whatsOn {
'results': selected[]->[@.endDate >= '2022-01-06' || @.date >= '2022-01-06']
}
} | order(_updatedAt desc)[0]Let me break down what's happening:
selected[]->dereferences all items in your selected array[@.endDate >= '2022-01-06' || @.date >= '2022-01-06']filters the dereferenced array- The
@refers to the current element in the array being filtered - The
||(OR) operator checks either condition
However, if you want to handle the conditional logic more explicitly (checking endDate first if it exists, otherwise falling back to date), you can use the defined() function:
*[_type == 'page'] {
whatsOn {
'results': selected[]->[@.endDate >= '2022-01-06' || (!defined(@.endDate) && @.date >= '2022-01-06')]
}
} | order(_updatedAt desc)[0]This ensures that if endDate exists and passes the date check, it includes the event. If endDate doesn't exist, it falls back to checking date.
Or, for a cleaner approach using the coalesce operator:
*[_type == 'page'] {
whatsOn {
'results': selected[]->[@.endDate >= '2022-01-06' || coalesce(@.endDate, @.date) >= '2022-01-06']
}
} | order(_updatedAt desc)[0]The coalesce() function returns the first non-null value, so it'll use endDate if it exists, otherwise date.
Pro tip: Instead of hardcoding the date, you can use the now() function to always compare against the current date:
*[_type == 'page'] {
whatsOn {
'results': selected[]->[@.endDate >= now() || coalesce(@.endDate, @.date) >= now()]
}
} | order(_updatedAt desc)[0]This way your query automatically filters out past events without needing to update the date string! The pipeline components documentation has more details on how filtering works within projections.
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.