Filter duplicate references & set default author in reference array

22 replies
Last updated: Jan 28, 2026
2 questions regarding an array of references:
1. Is there an easy way to filter out any already references already added to the parent array from the list of available array references in the default dialog dropdown? Should this potentially be default behavior (or a setting)?
2. I'm trying to reference a default author for my post document type, but since its an array of a reference, I'm not quite sure how to nest it.
This is my current attempt that is not working:

// post.js
export default {
...
  {
      name: 'authors',
      title: 'Authors',
      type: 'array',
      initialValue: {
        _type: 'reference',
        to: {
          _type: 'person',
          _ref: params.'9122a1cc-40d0-4120-9f30-3e997007896c'
        }
      },
  },
...
}
AI Update

I can help you with both questions about arrays of references in Sanity!

1. Filtering out already-selected references from the dropdown

Yes, there's a way to filter out already-selected references from showing in the dropdown. You can use the options.filter property on your reference field inside the array. Here's how:

{
  name: 'projects',
  title: 'Projects',
  type: 'array',
  of: [
    {
      type: 'reference',
      to: [{type: 'sampleProject'}],
      options: {
        filter: ({document}) => {
          const existingRefs = document.projects?.map(item => item._ref).filter(Boolean) || []
          return {
            filter: '!(_id in $existingRefs)',
            params: {
              existingRefs
            }
          }
        }
      }
    }
  ]
}

This dynamically filters the reference list based on what's already been added to the array. The key is that the options go on the reference type inside the array, not on the array itself. More details on dynamic filters can be found in the reference type documentation.

You can also use the validation rule unique() to prevent duplicates, but that only throws an error after selection rather than hiding already-selected items from the list.

To make this reusable across multiple schemas, you can extract it into a utility function:

// utils/getFilter.js
export const getFilter = (document, field) => {
  const existingEntries = document[field]?.map(entry => entry._ref).filter(Boolean) || []
  return {
    filter: '!(_id in $existingEntries)',
    params: {
      existingEntries
    }
  }
}

// Then in your schema:
import { getFilter } from '../utils/getFilter'

options: {
  filter: ({document}) => getFilter(document, 'projects')
}

As for whether this should be default behavior - it's not currently, but the filtering approach gives you that control when you need it.

2. Setting a default reference in an array

For setting an initial value with a reference in an array, the initialValue needs to be an array containing reference objects. Here's the correct structure:

{
  name: 'authors',
  title: 'Authors',
  type: 'array',
  of: [
    {
      type: 'reference',
      to: [{type: 'person'}]
    }
  ],
  initialValue: [
    {
      _type: 'reference',
      _ref: '9122a1cc-40d0-4120-9f30-3e997007896c'
    }
  ]
}

The key differences from your attempt:

  • initialValue should be an array (since the field type is array)
  • Inside that array, you only need _type: 'reference' and _ref - you don't need the nested to property in the initial value
  • The _type should be 'reference', not 'person'

This will automatically populate the array with your default author when a new document is created, and editors can still add more authors or remove the default one.

Note that this only works for new documents. If you need to add this default to existing documents, you'd need to use the Mutations API to update them. You can read more about initial values in the Initial Value Templates documentation.

Show original thread
22 replies

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?