Are there some limitations on -> when nested like this?
Looking at your query, person->firstname should actually work fine in GROQ - there are no inherent limitations on nested dereferencing. The -> operator works in nested contexts, so the issue is likely something else.
Here's what's probably happening:
Most likely issue: Field naming
Check if the field on the referenced person document is actually called firstname. It might be:
firstName(camelCase)first_name(snake_case)name(different field entirely)
When you write person and see {_ref: "...", _type: "reference"}, that confirms the reference exists. But if person->firstname returns nothing, the referenced document probably doesn't have a firstname field.
Solution: Use a projection to see what fields exist
Try this to inspect what's actually in the referenced person document:
*[_type == "collection"] {
"title": collection_title,
"books": collection_books[]{
"title": collection_book->book_title,
"persons": collection_book->persons[]{
"type": type,
"personData": person->
}
}
}This will return the entire referenced person document, showing you what fields are actually available.
Once you know the correct field name:
*[_type == "collection"] {
"title": collection_title,
"books": collection_books[]{
"title": collection_book->book_title,
"persons": collection_book->persons[]{
"type": type,
"firstname": person->firstName // or whatever the actual field name is
}
}
}Alternative: Use explicit projection syntax
If direct field access still doesn't work (which would be unusual), you can use projection syntax:
"persons": collection_book->persons[]{
type,
"firstname": person->{firstname}.firstname
}Or to get multiple fields from the person:
"persons": collection_book->persons[]{
type,
"personInfo": person->{
firstname,
lastname,
email
}
}The nested -> operator works fine in GROQ as described in Sanity's projections documentation, so this is almost certainly a field naming issue. Check your actual document structure to confirm the field name.
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.