Groq query issue with getting movies and character names for each person in the Sanity movies database.
The issue you're encountering is about scope levels with the parent operator (^). When you're inside the castMembers array filter, you need to reference the person's _id from two levels up, not just one.
Here's what's happening:
- First
^= the movie document - Second
^(^.^) = the person document (what you actually need)
So your query should use ^.^._id instead of ^._id:
*[_type=='person']{
_id,
"slug": slug.current,
"image": image{
asset->{
url
}
},
name,
"movies": *[_type=='movie' && references(^._id)]{
title,
"slug": slug.current,
"poster": poster{
asset->{
url
}
},
"as": castMembers[person._ref == ^.^._id]{
characterName
}
}
}The scope breakdown:
- You're in the outer person document
- You descend into the movie subquery (
^._idnow refers to the movie) - You descend into the
castMembersarray filter (you need^.^._idto get back to the person)
As explained in the GROQ parent operator documentation, you can chain multiple parent operators to traverse multiple levels up in scope.
For returning a string instead of an array, you can use the string::join() function:
"as": string::join(castMembers[person._ref == ^.^._id].characterName, ", ")This will take all the characterName values and join them into a single comma-separated string. If there's only one character, it'll just return that string. If someone played multiple characters in the same movie, they'll all be listed together.
The complete query would be:
*[_type=='person']{
_id,
"slug": slug.current,
"image": image{
asset->{
url
}
},
name,
"movies": *[_type=='movie' && references(^._id)]{
title,
"slug": slug.current,
"poster": poster{
asset->{
url
}
},
"as": string::join(castMembers[person._ref == ^.^._id].characterName, ", ")
}
}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.