Happening this week! Hear how Amplitude built a self-serve marketing engine to drive growth 🚀

Reference

A schema type for referencing other documents.

In a reference field you can search for, browse and select references to other documents, or create new documents of the appropriate type in a new pane

Relations between documents are modeled using the reference type. To model a one-to-many relation, store the references in an array.

References can be either strong (default) or weak. A strong reference will enforce that the document it points to actually exists, and will not allow deletion of a document that any other document refers to. A weak reference allows pointing to documents that may not exist (yet) or may have been deleted.

Gotcha

Whether a reference should be strong or weak is configured by setting the weak property on the reference field. Note that merely changing this property won't automatically update reference fields in the data store.

When working in Sanity Studio, the reference input allows you to search for already existing documents, or create and publish new documents of the appropriate type inline from the place of referral. In order to secure referential integrity, the referring document will be blocked from publishing until the new, referenced, document has been published. The exception is if the reference has the property weak: true.

Protip

For a more in-depth discussion on how to think about references in Sanity, we recommend reading the supplementary article Connected Content.

Properties

  • REQUIREDtypestring

    Value must be set to reference.

  • REQUIREDnamestring

    Required. The field name. This will be the key in the data record.

  • REQUIREDtoarray

    Required. Must contain an array naming all the types which may be referenced e.g. [{type: 'person'}]. See more examples below.

  • weakboolean

    Default false. If set to true the reference will be made weak. This allows references to point at documents that may or may not exist, such as a document that has not yet been published or a document that has been deleted (or indeed an entirely imagined document).

  • titlestring

    Human readable label for the field.

  • hiddenboolean | function

    If set to true, this field will be hidden in the studio. You can also return a callback function to use it as a conditional field.

  • readOnlyboolean | function

    If set to true, this field will not be editable in the content studio. You can also return a callback function to use it as a conditional field.

  • descriptionstring

    Short description to editors how the field is to be used.

  • initialValueObjectOrResolverFunction

    The initial value that will be used when creating new values from this type. Can be either the literal value or a resolver function that returns either the literal value or a promise that resolves to the initial value.

  • deprecated{ reason: String }

    Marks a field or document type as deprecated in the studio interface and displays a user-defined message defined by the single required reason property.

    If you deploy a GraphQL API schema, this property will translated into the @deprecated directive.

Options

  • disableNewboolean

    Disables inline creation of new documents from the reference field. Defaults to false.

  • filterstring | function

    Additional GROQ-filter to use when searching for target documents. The filter will be added to the already existing type name clause.

    If a function is provided, it is called with an object containing document, parent and parentPath properties as well as a convenient getClient() method, and should return an object containing filter and params. As of v2.4.0 this function can optionally be async and return a Promise that resolves to an object containing filter and params.

    Note: The filter only constrains the list of documents returned at the time you search. It does not guarantee that the referenced document will always match the filter provided.

  • filterParamsobject

    Object of parameters for the GROQ-filter specified in filter.

Validation

Learn more about validation
  • required()function

    Ensures that this field exists.

  • custom(fn)function

    Creates a custom validation rule.

Default reference

Define the movie's director as a reference to a person:

Input

{
  name: 'movie',
  type: 'object',
  fields: [
    {
      title: 'Director',
      name: 'director',
      type: 'reference',
      to: [{type: 'person'}]
    }
  ]
}

Output

{
  "_type": "reference",
  "_ref": "ffda9bed-b959-4100-abeb-9f1e241e9445" /* This could be the id of Jessica Chastain */
}

Weak reference

Define the screening's movie as a weak reference to a movie, thereby allowing the movie to be deleted without deleting the screening first:

Input

{
  name: 'screening',
  type: 'document',
  fields: [
    {
      name: 'movie',
      title: 'Movie',
      type: 'reference',
      weak: true,
      to: [{type: 'movie'}],
      description: 'Which movie are we screening'
    },
  ]
}

Output

{
  "_type": "reference",
  "_ref": "93f3af18-337a-4df7-a8de-fbaa6609fd0a" /* Movie id */
  "_weak": true
}

Reference multiple types

The directors field is an array which can contain both person and bovinae (in the rare occasion a cow would direct a movie) references:

Input

{
  title: 'Directors',
  name: 'directors',
  type: 'array',
  of: [
    {
      type: 'reference',
      to: [
        {type: 'person'},
        {type: 'bovinae'}
      ]
    }
  ]
}

Output

[
  {
    "_type": "reference",
    /* this could be the id of Yvonne, the escaped cow */
    "_ref": "9b711031-3744-47ab-9bb7-1bceb177d0d0"
  },
  {
    "_type": "reference",
    /* this could be the id of Matt Damon */
    "_ref": "ffda9bed-b959-4100-abeb-9f1e241e9445"
  }
]

Additional static filter

If providing a target schema type is not enough to provide a meaningful set of search results, you may want to further constrain the search query:

Input

{
  title: 'Director',
  name: 'director',
  type: 'reference',
  to: [{type: 'person'}],
  options: {
    filter: 'role == $role',
    filterParams: {role: 'director'}
  }
}

Output

{
  "_type": "reference",
   /* this could be the id of some director */
  "_ref": "9b711031-3744-47ab-9bb7-1bceb177d0d0"
},

Additional dynamic filter

If you want to further constrain the search result, but need properties from the surrounding document or object/array, you can use the function form for filter:

Input

{
  title: 'Director',
  name: 'director',
  type: 'reference',
  to: [{type: 'person'}],
  options: {
    filter: ({document}) => {
      // Always make sure to check for document properties
      // before attempting to use them
      if (!document.releaseYear) {
        return {
          filter: 'role == $role',
          params: {role: 'director'}
        }
      }
      
      return {
        filter: 'role == $role && birthYear >= $minYear',
        params: {
          role: 'director',
          minYear: document.releaseYear
        }
      }
    }
  }
}

Output

{
  "_type": "reference",
   /* this could be the id of some director,
    * born after the movie was released */
  "_ref": "9b711031-3744-47ab-9bb7-1bceb177d0d0"
}

Additional async filter

If you want to constrain your filter based on factors available elsewhere in your content lake, you can specify your filter as an asynchronous function.

Input

{ 
  // Somewhat contrived example that will make the reference field accept any document of a valid type except the most recently published
  name: 'personRef',
  type: 'reference',
  to: [{type: 'director'}, {type: 'actor'}, {type: 'producer'}],
  options: {
    filter: async ({getClient}) => {
      const client = getClient({apiVersion: '2023-01-01'})
      const latestPersonId = await client.fetch(
        '*[title in ["director", "actor", "producer"] && _id in path("*")] | order(_createdAt desc) [0]._id'
      )
      return {
        filter: '_id != $latestPersonId',
        params: {latestPersonId: latestPersonId},
      }
    },
  },
}

Output

{
  "_type": "reference",
   /* this could be the id of some director, actor, or producer */
  "_ref": "9b711031-3744-47ab-9bb7-1bceb177d0d0"
}

Disable new document creation

If you wish to disable the inline creation of new document from the reference field. This is done by setting the disableNew option to true.

{
  title: 'Director',
  name: 'director',
  type: 'reference',
  to: [{type: 'person'}],
  options: {
    disableNew: true,
  }
}

Nonexistent reference

Sometimes the reference field may show an error message like <nonexistent reference>. This usually happens when creating documents with a client library and can mean one of two things:

  • The document with the ID you are referencing does not exist
  • The field does not allow references to the document type of the document ID you tried to reference

Create reference programmatically

If you want to create a reference to another document when using our APIs, you need to know the ID of the document you want to create a reference to. Then you need to add that to an object with the following form:

{
  _type: 'reference',
  _ref: 'id-of-reference-document'
}

Here's an example using the Javascript client:

import {createClient} from '@sanity/client'

export const client = createClient({
  projectId: 'your-project-id',
  dataset: 'your-dataset-name',
  useCdn: true,
  apiVersion: '2023-05-03',
  token: process.env.SANITY_SECRET_TOKEN // Must have write access
})

client.create({
  _type: 'book',
  title: 'Some book title',
  author: {
    _type: 'reference',
    _ref: 'id-of-author-document'
  }
})
.then(result => {
  console.log(`Created book with id: ${result._id}`)
})

Writing GROQ queries for references

References by default are bi-directional and can be queried from either side of their relationship. For a movie that has an actors array referencing multiple person documents, we can join the person data to the movie by dereferencing its data, but we can also query all movies associated with a person.

Join the actor data onto movie data

*[_type == "movie"] {
  ...,
  "actors": actors[]{
    ...
    person->
  }
}

Get all movies for a person

*[_type=="person"]{
  name,
  "relatedMovies": *[_type=='movie' && references(^._id)]{ 
  	title,
  	slug,
  	releaseDate
	}
}

Was this article helpful?