Unset field in array items using Sanity client patch operation

3 replies
Last updated: Apr 6, 2022
Hi, I have a document that contains an array of items and I am hoping to unset a field in each item. More specifically, in the representative data below where the ‘contentArray’ array contains two elements, I want to
set()
the
projects
key to any empty array (or
unset()
, not sure which).
Data looks like:

{
  "_id": "9c780fd3-0e54-40ad-80c8-fd27dc19359f",
  "contentArray": [
    {
      "_key": "3cd487d4bd8c",
      "_type": "sectionProjectsGrid",
      "projects": [
        {
          "_key": "f880b5219313",
          "_ref": "05064724",
          "_type": "student",
          "_weak": true
        },
        {
          "_key": "432d0796461d",
          "_ref": "65e99226-fcc3-47e2-9419-d4095961d4e1",
          "_type": "student",
          "_weak": true
        }
      ]
    },
    {
      "_key": "0d5871d6ce7b",
      "_type": "sectionProjectsGrid",
      "projects": []
    }
  ],
  "title": "Home"
}
I tried using the JS version of the Sanity Client:

Semi-pseudo code:

sanityClient
    .patch('_id')
    .unset(['contentArray.projects'])
    .commit()
Not sure how to access each element of the ‘*contentArray’* array in the
unset()
method
I tried to loop through each contentArray element but this didn’t work:

contentArray.forEach((item, index) => {
    sanityClient
    .patch('_id')
    .unset([``contentArray[${index}].projects``])
    .commit()
})
or setting to empty array:
.set({contentArray[${index}].projects: []})

Thanks in advance for any suggestions
AI Update

I understand your challenge! You're trying to unset or clear the projects field within each item of your contentArray. The tricky part is that Sanity's patch operations don't support wildcard paths like contentArray[*].projects directly.

Here are your best options:

The most reliable approach is to use the _key values to target each array item specifically:

sanityClient
  .patch('9c780fd3-0e54-40ad-80c8-fd27dc19359f')
  .unset([
    'contentArray[_key=="3cd487d4bd8c"].projects',
    'contentArray[_key=="0d5871d6ce7b"].projects'
  ])
  .commit()

If you need to do this dynamically, fetch the document first and build the paths:

const doc = await sanityClient.getDocument('9c780fd3-0e54-40ad-80c8-fd27dc19359f')

const pathsToUnset = doc.contentArray
  .filter(item => item.projects && item.projects.length > 0)
  .map(item => `contentArray[_key=="${item._key}"].projects`)

if (pathsToUnset.length > 0) {
  await sanityClient
    .patch(doc._id)
    .unset(pathsToUnset)
    .commit()
}

Option 2: Replace the entire array

If you want to set all projects to empty arrays (rather than removing the field entirely), you can fetch the document, modify it in JavaScript, and set the entire contentArray:

const doc = await sanityClient.getDocument('9c780fd3-0e54-40ad-80c8-fd27dc19359f')

const updatedContentArray = doc.contentArray.map(item => ({
  ...item,
  projects: []
}))

await sanityClient
  .patch(doc._id)
  .set({ contentArray: updatedContentArray })
  .commit()

Why your attempts didn't work

Your loop approach was close, but each iteration created a separate patch transaction. The syntax contentArray[${index}].projects uses numeric indices, which aren't reliable in Sanity because array items can be reordered. Sanity's patch operations work better with _key references for array items.

The unset(['contentArray.projects']) approach treats the entire array as having a single projects property, which isn't how nested array items work.

unset() vs set() to empty array

  • unset(): Completely removes the field from the document
  • set({ projects: [] }): Keeps the field but makes it an empty array

Choose based on your schema and whether you want the field to exist or not. If your schema expects the field to always be present, use set() with an empty array.

The key takeaway is to use _key references when targeting specific items within arrays. This gives you precise control over nested fields in array items without having to replace the entire array structure.

Show original thread
3 replies
Hi Steve. If you want to unset all the
projects
arrays inside of
contentArray
items, you could use JSONMatch like:

import sanityClient from 'part:@sanity/base/client'

const client = sanityClient.withConfig({ apiVersion: '2022-04-05' })

client
    .patch('9c780fd3-0e54-40ad-80c8-fd27dc19359f')
    .unset(["contentArray[*].projects"])
  .commit()
  .then((res) => {
    console.log(res, ' updated')
  })
  .catch((err) => {
    console.error('Transaction failed: ', err.message)
  })
Unset will remove the
projects
arrays from the JSON, as is customary in Sanity when an array is empty.
thanks
user A
(as usual!) … worked like a charm and I learned about JSONMatch to target items in patches like set(), unset(), etc
Glad that works for you, Steve! 🙌

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?