Filter referenced documents during expansion in Sanity GROQ query

8 replies
Last updated: Jan 12, 2026
Hello everyone. Is it possible to filter as you expand a reference (in a sub doc)? I feel like I am overthinking this.
If I have something like :


# example: every series has a volume. Some volumes have a download link and some do not
# query every series, but for each series keep only the volumes whose download_link field is not empty/null/undefined

*[
  _type == "series" &&
  // defined(volumes[] -> download_link) // should the filtering be done here? Is this the right approach?
] {
  _id,
  title,
  volumes[] -> {     // or does the filtering have to be done here?
    _id,
    title,
    download_link,
  }
}
AI Update

You're not overthinking this at all! Filtering references in GROQ can be done in multiple ways, and the key is understanding where to apply your filter. For your use case, you want to filter the dereferenced volumes to only include those with a download_link.

The best approach is to filter the array after dereferencing, like this:

*[_type == "series"] {
  _id,
  title,
  "volumes": volumes[]->[ defined(download_link) ] {
    _id,
    title,
    download_link
  }
}

Here's what's happening:

  • volumes[]-> dereferences all the volume references
  • [ defined(download_link) ] filters the dereferenced volumes, keeping only those where download_link is not null/undefined
  • The final { } projection shapes what fields you want from those filtered volumes

You can also write this slightly differently by filtering before the projection:

*[_type == "series"] {
  _id,
  title,
  "volumes": volumes[]->[ defined(download_link) ]
}

This will return the complete volume documents (all fields) that have a defined download_link.

Why not filter at the top level? Your commented approach defined(volumes[]->download_link) wouldn't work as intended because it would filter entire series documents based on whether ANY volume has a download link, not filter the volumes themselves. You want to keep all series but filter their volumes arrays.

The pattern array[]->[ filter ] is the standard GROQ approach for filtering dereferenced arrays, and it's exactly what you need here. According to Sanity's GROQ documentation, GROQ queries work as pipelines where you can chain filtering and projection operations, which is what you're doing with the array dereference and filter.

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