Customizing Sanity Studio and sorting seminars based on lecturers

27 replies
Last updated: Nov 5, 2021
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.

Instead of
_type == "seminar" && $seminarId == lecturers[].lecturer.__ref
try
_$seminarId in lecturers[].lecturer.__ref
.Because
_lecturers[].lecturer.__ref
returns an array, you want to check if
$seminarId
is inside the array not that it is equal to it
When I change it to "in" i get nothing return 🤔
What I am trying to do is to return the seminars which have a reference to the lecturer I click in the documentList. This is how it looks for my authors (which follow the categoryId example from the article from the docs)
Shouldn't be the
$lecturerid
used instead, not the
$seminarId
?
oh, this is just a naming oversight on my part, it doesn't change the result from the event. Halfway working code looks like this:
Without the " == " and the "[0] there is no output. This only gives me one of the seminars the lecturer has appeared on however, but I want it to show all 😅
I will add that this query in Studio Vision is what i think is equivalent (based on testing with my authors) , and it gives the following output:
But adding either "0" or "1" gives me either of the seminars the lecturer is featured:
What's the result of
*[_type == "seminar"].lecturers[].lecturer._ref
in Vision ?
And what
lecturers[].lecturer
contains?From your first screen I guess it's
_type
and
_ref
fields, right?
That's right.
If it helps, it looks like this:
So based on what you gave to me, this should work.
hmm, "l1" would be the same as my $lecturerId ?
When you used the
in
keyword, are you sure you wrote it
id in array[]
?
Yep
"l1"
is
$lecturerId
hmmm, for some reason this still doesn't yield any output for me 🤔 This is exactly what you told me try first aswell 🤔
Really strange. Are you sure you don't have any document in draft?
Is it still returning nothing in Vision?
Everything is in a published state atleast, not sure if there is anything else i could do to be sure 🤔
"lecturers" is of type "object" called lecturerContainer, and "lecturer" is a reference to a document type called lecturer. Not sure if this can create a problem..
lecturers
is an array of object not directly an object right?
yes, sorry. Lecturers is an array that contains lecturerContainer objects
not sure if i need the "to: {type: 'lecturer'}"
I don't think too as it's not an array of references.But I don't think your schema is the cause of the problem.
Maybe try it, who knows...
Hey Eirik! Can you share the url of the query you're running? It's located above the results in Vision.
I've been told that i don't need to pursue it further. I believe what Sixclones did is supposed ot work, so I'll be taking the knowledge with me. But unfortunately I have to stop here 😅
Thanks for the help 👍

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?