🔮 Sanity Create is here. Writing is reinvented. Try now, no developer setup

Understanding the use of `^` and `@` operators in GROQ queries for accessing parent and current scopes.

6 replies
Last updated: May 29, 2023
What should my GROQ be to get the root document's title from a custom object's field? I feel like I should be able to just use
but that's just returning null.
May 29, 2023, 5:15 PM
You can traverse up in scope using the parent operator (
), and they can be chained together (e.g.,
May 29, 2023, 7:44 PM
What's the "special variable"
for then? I thought that I could access the root document with it?
May 29, 2023, 8:20 PM
is whatever’s currently in scope.
May 29, 2023, 8:21 PM
Maybe this will help because I'm still confused. The following code is from a custom seo object which I've added to my page document schema. I want to get the title from the page document this object is being used on.
// studio/schemas/objects/seo.ts

initialValue: async (_, context) => {
    const client = context.getClient;
    const title = await client({ apiVersion })?.fetch(`[@][].title`);

    return title || '';
May 29, 2023, 8:26 PM
Sorry, I should clarify.
is whatever’s in scope of the current GROQ query, but it can’t be used to establish a query. In this case, the query being provided to
doesn’t provide any context about what it’s after, as the client will not infer the current document and pass it along. Instead, it will usually be provided with an
, which will be used in the query.
Here’s an example that hopefully shows how
work. When you dereference, you are performing a subquery not unlike the implementation of
below (so the
filter is close to or the same as `author->`—minus the projection with `authorDetails`—but I’ve used this method to demonstrate a point.

*[_type == 'post'][0]{
  'author': *[_type == 'author' && _id == ^.author._ref]{
    'authorDetails': @
  'postDetails': @
In the query
*[_type == 'author' && _id == ^.author._ref]
, we want to compare the
that’s in scope (i.e., of the author) to the
value of the parent (i.e., the post). The
operator lets us do this by looking at the parent scope. This only works because we have a
document in the context of this GROQ query. We couldn’t query for
*[_type == 'author']
and be able to use the
operator to look any higher than the root.
is returning us the current scope at that point, which is in the context of the
*[_type == 'author' && _id == ^.author._ref]
is returning us the current scope at that point, which is in the context of the
*[_type == 'post'][0]
As for your desire to fetch a field on the current document in the
callback, I don’t believe that will be possible since at that point, the document doesn’t exist yet. Initial values are only set on document creation, so there won’t be a title to fetch. Hope this helps!
May 29, 2023, 10:10 PM
Hey thanks for that detailed response! That makes much more sense now.
May 29, 2023, 11:45 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?