How to expand nested references while keeping sibling items in array?

3 replies
Last updated: Nov 29, 2025
Maybe I'm losing my mind, or don't have enough caffeine in my system, but I can't work out how to expand a nested reference, but also keep its sibling. I have a
submenuItems
array that can contain URL or a reference to another document. However, I can't seem to expand any references it encounters without losing the sibling submenuItem that happens to be a normal url/link.
AI Update

You're not losing your mind! This is a common GROQ challenge when working with mixed arrays containing both references and regular objects. The issue is that when you use the dereference operator (->), it only works on reference items and filters out non-references.

Here's the solution: use a projection with conditional dereferencing to handle both types:

submenuItems[] {
  _type == 'reference' => @->,
  _type != 'reference' => @
}

Or more explicitly:

submenuItems[] {
  ...,
  _type == 'reference' => {
    "item": @->
  },
  _type != 'reference' => {
    "item": @
  }
}

What's happening here:

  • The [] operator iterates through your array
  • The conditional => checks each item's type
  • For references, @-> dereferences them (the @ refers to the current item)
  • For non-references (like your URL objects), @ just returns them as-is

A cleaner approach if you want to flatten the structure:

submenuItems[] {
  _type == 'reference' => @->{
    // explicitly select fields from the referenced document
    _id,
    title,
    slug
  },
  _type != 'reference' => {
    // return the URL object as-is
    ...
  }
}

Pro tip: If your URL items have a specific _type (like urlLink), you can be even more specific:

submenuItems[] {
  _type == 'reference' => @->,
  _type == 'urlLink' => @
}

This pattern works because GROQ evaluates each conditional in order and returns the first match. Your non-reference siblings will stay intact while references get expanded. No more missing menu items!

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