GROQ: Reference parent person ID in nested castMembers filter
personget their movies and get their characterName.
This is works except it’s for one person I need to hardcode the
_idin the
asbit
*[_type=='person' && _id=="person_sigourney-weaver"]{
_id,
"slug": slug.current,
"image": image{
asset->{
url
}
},
name,
"movies": *[_type=='movie' && references(^._id)]{
"fakeId": ^._id,
title,
"slug": slug.current,
"poster": poster{
asset->{
url
}
},
"as": castMembers[person._ref == "person_sigourney-weaver"]{
characterName
}
}
}"as": castMembers[person._ref == ^._id]{ does not work, it returns an empty array.Where am I going wrong?
And if possible, rather than returning
asas an array, could it come back a string?
Thank you
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, ", ")
}
}Show original thread3 replies
Was this answer helpful?
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.