How to dereference nested references in GROQ projections?

9 replies
Last updated: Jan 24, 2026
Can someone help me format this query? I have a document (type A) that has two arrays, which each reference other documents (type B & C, respectively). I initially queried for documents of type A && with the right name, then made two naked projections for each array of documents, like this:`'typeB': typeBDocuments[].typeBDocument->` so that they dereferenced (I think that is the right terminology?).
The problem is that these documents each have references inside them, and so I either need to learn how to do multi-layer dereferencing, or I need to query documents of type B & C which are referenced by the type A document.

I’m happy to give access to the repository if you want to see the thing.
AI Update

Based on your description, you're dealing with nested references in GROQ, and you're on the right track! The -> operator does indeed dereference references, and you can chain multiple dereferences to follow nested references as deep as you need.

For multi-layer dereferencing, you can simply chain the -> operators. Here's how it works:

*[_type == "typeA" && name == "yourName"]{
  'typeB': typeBDocuments[].typeBDocument->{
    // Fields from type B document
    title,
    someField,
    // Now dereference nested references inside type B
    'nestedRef': nestedReference->
  },
  'typeC': typeCDocuments[].typeCDocument->{
    // Fields from type C document
    name,
    // Dereference nested references inside type C
    'nestedRef': anotherReference->{
      // You can even go deeper
      field1,
      field2,
      'deeperRef': yetAnotherReference->
    }
  }
}

The key points:

  1. Chaining works: You can use -> multiple times to follow references as deep as needed
  2. Array handling: When your reference is inside an array, the syntax array[]-> automatically maps over the array and dereferences each item
  3. Projection control: Inside each {}, explicitly list which fields you want from the dereferenced document

If you want to be more selective about which fields come back at each level, you can be explicit:

*[_type == "typeA" && name == "yourName"]{
  name,
  'typeBData': typeBDocuments[].typeBDocument->{
    _id,
    title,
    description,
    'relatedItem': relatedItemRef->{
      _id,
      name,
      imageUrl
    }
  }
}

This approach is covered in the projections documentation, which explains how projections let you follow references and build custom data structures.

The alternative approach you mentioned—querying type B & C documents separately—would be less efficient since you'd need multiple queries and then manually match them up in your application code. The nested dereferencing approach keeps everything in a single query and returns the exact shape you need.

If you're still having trouble with the syntax, feel free to share your actual query and schema structure, and the community can help you format it more specifically!

Show original thread
9 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?