How to structure content in Sanity.io & use GROQ queries for filtering & referencing related documents.
19 replies
Last updated: Feb 23, 2023
V
hi. i’m struggling a lot with something: i have a Films document type that references one Director (which is an other document type). in a Director page, i want a field named “relatedFilms” which is an array of references to Films, but i’d like to only be able to choose films that reference the current Director
Feb 23, 2023, 11:45 AM
D
Feb 23, 2023, 11:55 AM
D
Feb 23, 2023, 11:56 AM
V
i see! so, if i want to adapt this example with my content, do you have an idea of how it would be?
Feb 23, 2023, 1:40 PM
V
here is how my schema looks, but in my Sanity desk, the search query returns no result for “”
import {RiUserLine as icon} from 'react-icons/ri' export default { title: 'Directors', name: 'directors', type: 'document', icon, fields: [ { title: 'Name', name: 'name', type: 'string', }, { title: 'Slug', name: 'slug', type: 'slug', description: 'Click on *Generate* to create the slug', options: { source: 'name', slugify: (input) => input.toLowerCase().replace(/\s+/g, '-').slice(0, 200), }, }, { title: 'Related Films', name: 'relatedFilms', type: 'array', description: "Reference the director's films you want to showcase", of: [ { type: 'reference', to: [{type: 'films'}], options: { filter: ({document}) => { return { filter: 'director == $director', params: {director: document.name}, } }, }, }, ], }, ], }
Feb 23, 2023, 1:45 PM
Rather than create a two-way reference it might cause less headaches longterm to just find the latest 3 films by that director in a GROQ request which would look like:
But if you want to do the array of references then you actually need a dynamic filter using
https://www.sanity.io/docs/reference-type#8118f73f6758
*[_type == "director"]{ ..., *[_type == "film" && references(^._id)][0..2] | order(date desc) }
^.to reference the parent document:
https://www.sanity.io/docs/reference-type#8118f73f6758
Feb 23, 2023, 1:47 PM
S
In addition you could also create a pane with document lists in there , which use the query
And the lists would be in sync with your content and would not need to be kept up to date
user P
posted before. This way you leverage the references instead of creating bilateral references, which are not needed 🙂And the lists would be in sync with your content and would not need to be kept up to date
Feb 23, 2023, 4:20 PM
V
user J
oh waouw! i did not know about this. i’ll give this a try. do you think it may cover my needs?Feb 23, 2023, 4:50 PM
V
thank you for the answers everybody 🙂
Feb 23, 2023, 4:50 PM
V
alright so for now i just tried to do the array of reference as i intended, in the first place, with this piece of code:
but it does not return any result for now.. though in my API, each film should have a director field, with a name property inside.
is it correlated with the fact that when i inspect my API response of a film, the director field does not contain any data but a _ref and and _type? which is odd, because there is
of: [ { type: 'reference', to: [{type: 'films'}], options: { filter: 'director.name == $directorName', filterParams: {directorName: '^.name'}, }, }, ],
is it correlated with the fact that when i inspect my API response of a film, the director field does not contain any data but a _ref and and _type? which is odd, because there is
Feb 23, 2023, 5:43 PM
V
okay i have the feeling i’m getting close to it!
of: [ { type: 'reference', to: [{type: 'films'}], options: { filter: 'director._ref == $directorId', filterParams: { directorId: '^._id' } } }, ],
Feb 23, 2023, 6:00 PM
V
i can achieve this by putting manually a director id instead of the param, but now i need to retrieve the document id automatically
Feb 23, 2023, 6:00 PM
S
As said before you should not do it like that 😊When you think about it the structure is:
you have directors and films. each film has a director it references. On the director doc you add a pane where you groq all the films, that reference the director.
Adding 2 way references will make your data structure very cumbersome in the end. This is why loading the references dynamically in a list like this is better!
In addition you can set up a custom structure, where you filter the films to their refrerenced directors. You do not need the array!
you have directors and films. each film has a director it references. On the director doc you add a pane where you groq all the films, that reference the director.
Adding 2 way references will make your data structure very cumbersome in the end. This is why loading the references dynamically in a list like this is better!
In addition you can set up a custom structure, where you filter the films to their refrerenced directors. You do not need the array!
Feb 23, 2023, 6:03 PM
V
i see! does your last sentence refer to the sanity-pane solution, or is it an other way of doing it?
Feb 23, 2023, 6:08 PM
S
You can add a custom desk structur e like this:
You can follow
this guide here if you want
// structure S.listItem() .title('Films') .schemaType('film') .child( S.documentList() .title('Film by Director') .filter('_type == "director"') .child( (directorId) => S.documentList() .title('Films') .filter('_type == "film" && director._ref == $directorId') .params({ directorId }) .menuItems(S.documentTypeList('film').getMenuItems()) .canHandleIntent( S.documentTypeList('film').getCanHandleIntent() ) ) .defaultOrdering([{ field: 'title', direction: 'asc' }]) )
this guide here if you want
Feb 23, 2023, 6:08 PM
V
oh great! alright, this is a lot of resources and help you provided me. i cannot thank you enough!
Feb 23, 2023, 6:10 PM
V
you rock!
Feb 23, 2023, 6:10 PM
S
Happy I could help! And I would recommend looking into our structured content ressources and maybe asking some question about the overall structure in content-strategy
Feb 23, 2023, 6:12 PM
S
You will see, you will unlock MASSIVE possibilities when you learn how to think in structured content :) Also this might help you as it helped me understand the power of GROQ :groq:
Feb 23, 2023, 6:13 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.