How AI is powering better personalization in e-commerce [with Vercel]. Sign up now →

Filter array to exclude already referenced sections in Sanity document

26 repliesLast updated: Nov 29, 2025

Hello amazing Sanity people 🌞 ! I am doing my head in trying to figure out how to write a filter query.I have a document with an array called
primary

primary
is an array of
item
objects.In item, instead of getting a list of all sections, I only want to see those which are not already referenced by my document.
Maybe this is actually very simple, but I can’t seem to work it out…

  name: 'item',
  title: 'Item',
  type: 'object',
  fields: [
    {
      name: 'section',
      title: 'Section',
      type: 'reference',
      to: { type: 'section' },
      options: {
        filter: ({ document, parent, parentPath }) => {
          console.log(document._id)

          return {
            filter: '!(^._id in *[_id==$document].primary[])',
            params: {
              document: document._id
            }
          }
        }
      }
    }
  ]

AI Update

I can help you filter out already-referenced sections from your reference field! The issue with your current query is the syntax - you're trying to access the parent document's array, but the approach needs adjustment.

Here's the corrected solution:

{
  name: 'section',
  title: 'Section',
  type: 'reference',
  to: { type: 'section' },
  options: {
    filter: ({ document }) => {
      // Get all section IDs already referenced in the primary array
      const referencedIds = document.primary
        ?.map(item => item.section?._ref)
        .filter(Boolean) || []

      return {
        filter: '!(_id in $referencedIds)',
        params: {
          referencedIds
        }
      }
    }
  }
}

What's happening here:

Important note: The filter function re-runs when the document changes, so as you add sections to your primary array, they'll automatically disappear from the available options in other items.

Making it reusable:

You can extract this into a utility function to keep your code DRY, as shown in this community example:

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

// Then in your schema:
options: {
  filter: ({ document }) => {
    const referencedIds = document.primary
      ?.map(item => item.section?._ref)
      .filter(Boolean) || []
    
    return {
      filter: '!(_id in $referencedIds)',
      params: { referencedIds }
    }
  }
}

This is a common pattern when building navigation menus, related content pickers, or any scenario where you want to avoid duplicate references in an array!

Show original thread
26 replies

Was this answer helpful?

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.

Related contributions