👋 Next.js Conf 2024: Come build, party, run, and connect with us! See all events

Filtering sub-documents in Sanity.io using the @ operator

8 replies
Last updated: Apr 17, 2023
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,
  }
}
Apr 8, 2023, 12:32 AM
Are you specifically looking only for series that contain volumes with a download link or do you want all of your series but then only filter the volume links array?
Apr 10, 2023, 8:13 PM
I would like the second one! Fine with getting all series and if the subsequent filtering of volumes yield no results that should be fine to have a series with volumes of array length zero. Is there a way to do that inside the query?
Apr 10, 2023, 8:15 PM
Got it! You want to do the filtering in the array then:
*[
  _type == "series" &&
] {
  _id,
  title,
  volumes[defined(@->.download_link)] -> { 
    _id,
    title,
    download_link,
  }
}
Apr 10, 2023, 8:17 PM
Wow thank you so much! Have not seen that syntax before. Much much appreciated !!
Apr 10, 2023, 8:29 PM
Yeah the @ operator us super handy!
Apr 10, 2023, 8:49 PM
user M
sorry to bug but I am getting a super weird issue where the query you provided does indeed work on Sanity Studio (vision) but not in my project. By not work, I mean that it returns an empty array (for the volumes). I’ve isolated the issue to the “@” symbol itself (i.e., if I just remove that part of the query, the rest of it appears to work). I have also copied/pasted the query from studio to my project. I’ve tried tinkering with the “@” operator in all sorts of ways but it doesn’t appear to do anything. I’ve tried:

# these work on sanity studio, but not in my project even if I copy/paste verbatim
volumes[defined(@->.download_link)] -> { /// rest of the query
volumes[defined(@["download_link"])] -> { /// rest of the query

# tried these as a hail mary solution but none worked.
volumes[defined(@[]->.download_link)] -> { /// rest of the query
volumes[defined(@.download_link)] -> { /// rest of the query
If it turns out that I am getting different behavior between Sanity Studio and my local project, is this a versioning issue? A known bug?

I am using
@sanity/client
and am updated to version 5.4.2, but to no avail.
Edit: Here is the code I am using to run my query. Identical to the query I am running in Sanity Studio. But I get different results for some reason
😭

export async function getDownloads(): Promise<Release[]> {
  const data: Release[] = await client.fetch(`
    *[
      _type == "series" && 
      length(volumes[]) > 0
    ] {
      _id, 
      title,
      volumes[] -> {
        _id,
        title,
        download_link,
      }
    }
  `);
  return data;
}
Apr 16, 2023, 7:33 AM
I think it has to do with the Groq version. I was using V1, but had to specify version
2021-10-21
for the query to work!
Apr 16, 2023, 7:21 PM
Glad you got it working!
Apr 17, 2023, 4:40 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?