Understanding the use of `^` and `@` operators in GROQ queries for accessing parent and current scopes.
6 replies
Last updated: May 29, 2023
J
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
[@].titlebut 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.,
^.^.title).
May 29, 2023, 7:44 PM
J
What's the "special variable"
@for then? I thought that I could access the root document with it?
May 29, 2023, 8:20 PM
J
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.
Here’s an example that hopefully shows how
In the query
, we want to compare the
The
query.
The
As for your desire to fetch a field on the current document in the
@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
client.fetchdoesn’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
_id, which will be used in the query.
Here’s an example that hopefully shows how
^and
@work. When you dereference, you are performing a subquery not unlike the implementation of
authorbelow (so the
authorfilter 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': @ }
*[_type == 'author' && _id == ^.author._ref]
_idthat’s in scope (i.e., of the author) to the
author._refvalue 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
postdocument 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.
The
@in
authorDetailsis returning us the current scope at that point, which is in the context of the
*[_type == 'author' && _id == ^.author._ref]
The
@in
postDetailsis returning us the current scope at that point, which is in the context of the
*[_type == 'post'][0]query.
As for your desire to fetch a field on the current document in the
initialValuecallback, 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
J
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.