Filter seminars by nested lecturer reference in documentList()

27 replies
Last updated: Nov 29, 2025
Hey,I am customizing the Sanity Studio and have hit a roadblock on the S.documentList().filter() when trying to sort seminars based on lecturers. I've been following the guide:
https://www.sanity.io/docs/dynamically-group-list-items-with-a-groq-filter , and many of my prior sortings have worked out fine. The problem is this filter: ('_type == "seminar" && $seminarId == lecturers[].lecturer.__ref') which is similar to categoryId example of the article: ('_type == "post" && $categoryId in categories[]._ref')...
The problem is that in my code with extra nesting it doesnt seem to loop through lecturers[], as I only get a result if I specify an index like so: lecturers[0].lecturers._ref

Is it possible to do something like this with a filter only?

The data I am using this on is as follows:
AI Update

Looking at your issue with filtering seminars based on lecturers in the Structure Builder, the problem you're encountering is related to how GROQ handles nested array references.

The key difference between your filter and the working example from the documentation is the level of nesting. In the documentation example:

'_type == "post" && $categoryId in categories[]._ref'

The categories array contains direct references, so categories[]._ref works to extract all reference IDs.

However, in your case with:

'_type == "seminar" && $seminarId == lecturers[].lecturer.__ref'

You have an extra level of nesting - lecturers[] is an array of objects, and each object has a lecturer field that contains the reference. The issue is that lecturers[].lecturer.__ref doesn't properly flatten this nested structure in a filter comparison context.

The Solution

You need to use the in operator instead of ==, combined with proper array dereferencing:

.filter('_type == "seminar" && $lecturerId in lecturers[].lecturer._ref')
.params({lecturerId})

Key changes:

  1. Use in operator instead of == - this checks if the value exists anywhere in the resulting array
  2. Use _ref instead of __ref - the single underscore is the correct property name for references in GROQ
  3. The path lecturers[].lecturer._ref will properly extract all reference IDs from the nested structure

Complete Example

Here's how your dynamic filtered list should look:

S.documentTypeList('lecturer')
  .title('Seminars by Lecturer')
  .child((lecturerId) =>
    S.documentList()
      .apiVersion('2024-06-01')
      .title('Seminars')
      .filter('_type == "seminar" && $lecturerId in lecturers[].lecturer._ref')
      .params({lecturerId}),
  )

The lecturers[].lecturer._ref projection will create an array of all lecturer reference IDs from your nested structure, and the in operator will check if your $lecturerId parameter exists in that array.

This should work with your nested structure without needing to specify an index like [0]. The array projection syntax lecturers[].lecturer._ref automatically handles the iteration through all items in the lecturers array.

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