Linking coffee shops to amenities using array of references in Sanity.io

3 replies
Last updated: Jun 27, 2024
Hey Friends, I'm looking for a way to reference one document to many documents. My example is one coffee shop (table 1) to having many amenities (table 2)
"Table one: coffee shops
Table Two: Amenities (wifi, bathrooms)

I want to link that this coffee shop has 2 amenities(via referencing the IDs of two rows in the Amenities table. How do I do this?"

Here's an image of how a joins table would do this.

I read this page but didn't deliver.


https://www.sanity.io/docs/reference-type
AI Update

You're looking to create a one-to-many relationship in Sanity where one coffee shop can reference multiple amenities. This is a perfect use case for an array of references!

Here's how to set this up in your schema:

// coffeeshop.js (or in your schema definition)
{
  name: 'coffeeShop',
  type: 'document',
  title: 'Coffee Shop',
  fields: [
    {
      name: 'name',
      type: 'string',
      title: 'Shop Name'
    },
    {
      name: 'amenities',
      type: 'array',
      title: 'Amenities',
      of: [
        {
          type: 'reference',
          to: [{type: 'amenity'}]
        }
      ]
    }
  ]
}

// amenity.js (your amenities document type)
{
  name: 'amenity',
  type: 'document',
  title: 'Amenity',
  fields: [
    {
      name: 'name',
      type: 'string',
      title: 'Amenity Name'
    },
    {
      name: 'icon',
      type: 'string',
      title: 'Icon'
    }
  ]
}

The key is using an array field with of: [{ type: 'reference' }] inside it. This creates an ordered list of references to your amenity documents.

When you create a coffee shop in Sanity Studio, you'll see a nice interface where you can:

  • Search for existing amenities
  • Select multiple amenities
  • Reorder them by dragging
  • Create new amenities inline

The data will be stored like this:

{
  "_type": "coffeeShop",
  "name": "Blue Bottle",
  "amenities": [
    {
      "_type": "reference",
      "_ref": "amenity-wifi-id",
      "_key": "unique-key-1"
    },
    {
      "_type": "reference", 
      "_ref": "amenity-bathroom-id",
      "_key": "unique-key-2"
    }
  ]
}

To query this data with GROQ, you can dereference the amenities:

*[_type == "coffeeShop"] {
  name,
  "amenities": amenities[]->
}

This is the standard Sanity pattern for one-to-many relationships - no join tables needed! The reference is stored in the coffee shop document, and you can query in either direction since references are bidirectional.

If you need to query from the other direction (find all coffee shops that have a specific amenity), you can use the references() function:

*[_type == "amenity" && name == "wifi"] {
  name,
  "coffeeShops": *[_type == "coffeeShop" && references(^._id)] {
    name
  }
}

The array of references pattern is documented in the Sanity docs, and you can find more details about reference types here.

Sounds like you can use an array of references? Something like:

{
  title: “Amenities”,
  name: “amenities”,
  type: “array”,
  of: [
    {
      type: “reference”, 
      to: [
        {type: “amenity”}
      ]
   }
 ]
}
Rad I'll give this a try!
This worked thank you.
note: " " double quotes created an error.

` ` single quotes make it work.

defineField({          
            name: 'amenities',
            title: 'Amenities',
            type: 'array',
            of: [
                {
                type: 'reference', 
                to: [
                    {type: 'amenity'}
                    ]
                }
             ]
        }),

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?