Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Bidirectional references in Sanity.io for many-to-many relationships

12 replies
Last updated: Dec 31, 2020
Are many-to-many relationships possible using references (or anything else)? I was surprised not to find anything about that here, in the docs, or on SO, but surely there’s a way!
I have
items
and
categories
. Each item can have many categories and each category can have many items, which I can set up by adding a reference to each one, except those lists don’t know about each other. What I need is essentially to have one relationship between the two document types that I can set on either one. eg, if I set
item1
to have
categoryA
and then go to
categoryA
, I would expect to see
item1
listed on
categoryA
. Hope that makes sense!
Dec 28, 2020, 10:04 PM
References are bidirectional out of the box, but the studio currently doesn’t show incoming references to a document. You can however create an “input” or preview component that shows all the documents that has referenced it. Here’s a screenshot of one I made for debugging purposes on my own. Will see if I can find the code for it 👍 It wasn't made with the latest version of Sanity, so keep that in mind 😅😇 https://github.com/sanity-io/sanity/tree/victoria/incoming-refs-preview/packages/test-studio/src/previews/incoming-refs
Here’s how I queried for the references:

const query = `*[!(_id in path("drafts.**")) && references('${published._id}')]`
  const documents = useDocuments(published._id, query)
Dec 28, 2020, 10:27 PM
Thanks for the response
user H
! Can you expand on what bidirectional means for this context? It doesn’t look like it does what I need it to out of the box, so I don’t think it means what I’m hoping for.
To try another example: If I add
itemA
to the list of
items
on
category1
, I also expect
category1
to be added to a list of
categories
on
itemA
. If I then decide I don’t want
itemA
included in that category, I could make this change either by removing the category from
itemA
or by removing the item from the list on
category1
.
Goal: to be able to manage the same relationship between categories and items on either the category or the item. If it’s just a preview component, then it’s not actually part of the list, right?
Dec 28, 2020, 10:37 PM
I’ll take a look at your code to see if that helps though, thanks!
Dec 28, 2020, 10:37 PM
It sounds like you then need a custom input component, and that it’s maybe not as straight forward with references only👍 but by bidirectional I mean that when you reference documents they are “aware of each other”, they just don’t show up in the Studio. But you can list them using the
references
method in GROQ. if you reference a document (A) in document (B), you can do this to list all the references that exist to the document A:
references(<http://documentA.id|documentA.id>)
, which means that documentB will show up in that list 👍
Dec 28, 2020, 10:46 PM
Okay, thanks!
Dec 28, 2020, 10:49 PM
In your example, does
IntentLink
take you to the edit page of the preview item that it wraps? I might be able to get away with only having a true reference list on one of the types if the other at least lists all with an easy link to get to it.
Dec 28, 2020, 10:51 PM
Also, is
IntentLink
still available? It’s been difficult to follow tutorials without documentation of the
parts
and trying to figure out what’s going on in the source code, and then having the code also in the process of deprecating the parts system.
Dec 28, 2020, 10:52 PM
Yes that’s what the intent link does 👍 I think it’s still around 😊
Dec 28, 2020, 11:25 PM
Hi again
user H
😁 👋 Is it possible to implement the reference list without using structure builder? I may end up needing to get into that later anyway but haven’t needed it yet.
Dec 30, 2020, 2:29 AM
Maybe you can create an input component that’s not actually an input component? Meaning that it only displays a list, but is in the schema
Dec 30, 2020, 7:49 AM
This was super helpful, ended up making a list based on your example but also using Sanity UI and as an “input component” that doesn’t actually take input. Thanks so much and happy new year
user H
!
Dec 31, 2020, 12:32 AM
No problem! And that’s awesome, happy to hear you solved it! 😃 Happy new year 🎉
Dec 31, 2020, 8:15 AM

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?