Accessing grandparent object in GROQ query with ^ operator

23 replies
Last updated: Jan 28, 2026
Hi for some reasons I'm trying to get access to grandparent object but
^.^
is not working 😞
*[_type == 'post' && slug.current == $slug]{
  children[]->{
    'post': ^.^
  }
}
Except the
@
and
^
operators, I can't find anything that could do the job 😕
AI Update

I understand the frustration! Unfortunately, ^.^ doesn't work after the dereference operator (->) in your query, though I should be upfront that the official documentation doesn't explicitly explain why this limitation exists.

What we do know from the parent operator documentation is that ^ traverses up through projection scopes and can be chained as ^.^ for grandparent access. However, the reference access operator (->) internally executes a subquery to fetch the referenced document, which appears to create a context where the parent scope chain is no longer accessible—though the exact mechanics of this aren't fully documented.

What's Happening in Your Query

In your query:

*[_type == 'post' && slug.current == $slug]{
  children[]->{
    'post': ^.^  // This doesn't work
  }
}

The dereference creates a new query context for the referenced document, and the ^ operator can't traverse back through that boundary based on observed behavior.

Working Solutions

Option 1: Capture the parent before dereferencing

*[_type == 'post' && slug.current == $slug]{
  ...,
  children[]{
    'childData': @->,
    'post': ^
  }
}

Here, ^ inside the children[] projection (before dereferencing) correctly refers to the parent post document.

Option 2: Access specific fields before dereferencing

*[_type == 'post' && slug.current == $slug]{
  _id,
  title,
  'enrichedChildren': children[]{
    'ref': @,
    'child': @->,
    'parentId': ^._id,
    'parentTitle': ^.title
  }
}

Option 3: Restructure to keep post and children as siblings

*[_type == 'post' && slug.current == $slug][0]{
  'post': @,
  'children': children[]->
}

Option 4: Use a nested structure

*[_type == 'post' && slug.current == $slug] {
  'parentPost': @,
  'childrenWithData': children[]->
}

The practical workaround is to capture what you need from the parent scope before you dereference. Option 1 is usually the cleanest approach—it maintains access to the parent post while still getting your dereferenced child data.

Show original thread
23 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.

Was this answer helpful?