How to patch a field of an object in an array using the Sanity JavaScript client

7 replies
Last updated: May 29, 2023
Hey guys !I'm trying to patch a field of an object in an array with the js client, but I don't see how it's possible in a clean way.
Let's says I have something like this :

{
    "_id": 'aFuiYGWUw0SSAvMnYQafry',
    "entries": [
        {
            "_key": "BjDASDLOMkBsqk1tqRecKu"
            ...other keys and values
        },
        {
            "_key": "E0vulMwINU3H9ETBqXnRT7",
            ..oher keys and values
            "subentries": [
                {
                    "data": "saved datas",
                    "_key": "6b8c867d-36b9-4eff-97e0-9fd5be6c6ee4"
                },
                => insert data here
            ]
        }
    ]
}
For now, the only solution I found was to fetch the entire document, edit the result in JS and patch with the full data.
• It is not very clean, and need another request
• I lost some fields value, even if I checked that all data was there
Any better idea ?
AI Update

Good news - you can definitely do this in a cleaner way without fetching the entire document! Sanity's patch operations support targeting specific items within nested arrays using path conditions.

For your use case of inserting data into a nested subentries array, you can use the insert operation with a path that targets the specific parent entry by its _key. Here's how:

client
  .patch('aFuiYGWUw0SSAvMnYQafry')
  .insert('after', 'entries[_key=="E0vulMwINU3H9ETBqXnRT7"].subentries[-1]', [
    {
      _key: 'new-unique-key', // generate a unique key
      data: 'your new data'
    }
  ])
  .commit()

This approach:

  • Targets the specific entry in entries array using [_key=="E0vulMwINU3H9ETBqXnRT7"]
  • References the subentries array within that entry
  • Uses [-1] to reference the last item (or use a specific index like [0])
  • Inserts your new item after that position

If you want to update an existing item in the nested array instead of inserting, you can use set:

client
  .patch('aFuiYGWUw0SSAvMnYQafry')
  .set({
    'entries[_key=="E0vulMwINU3H9ETBqXnRT7"].subentries[_key=="6b8c867d-36b9-4eff-97e0-9fd5be6c6ee4"].data': 'updated data'
  })
  .commit()

The key is using JSONMatch-style path syntax with conditions like [_key=="value"] to target specific objects in arrays. This way you're only sending the minimal change needed, avoiding the fetch-edit-patch cycle and preventing data loss issues.

These operations are also "real-time safe," meaning they work correctly even when multiple users are editing simultaneously, which wouldn't be guaranteed with your fetch-then-replace approach. You can read more about patch operations in the docs.

Hi
user Q
, just I'm not sure yet what you're looking for...
Have a look at the first example on this doc page for patches -- it's not requesting any other records to do the `patch`; you'd just send this mutation query through the client, no?
https://www.sanity.io/docs/http-patches
You might need another query to get the values to fill in, but isn't that natural?

Clean if needed, for me anyway, but it could well be I'm missing what's really your concern here, so far....

Best, (Removed Name)
Let’s say I want to replace the value of a field in the second object of an array. I don’t see how I can use the index or the key there to updte a specific target without touching the others
Well, a patch lets you focus on just one object and one field in it, if you want, doesn't it?
I'm viewing this that you are targeting that object in the patch, not the array holding it, which shouldn't need touching?
hm, I think I got it :I was looking for a condition like this :
{ "set": { "body[_type==\"cta\"].text": "Do the thing!" } }


{
  "mutations": [
    {
      "patch": {
        "id": "aFuiYGWUw0SSAvMnYQafry",
        "set": {
          "entries"[_key==\"E0vulMwINU3H9ETBqXnRT7\"] : {
            "insert": {
              "after": "subentries[-1]",
              "items": ["=> insert data here"]
            }
          }
        }
      }
    }
  ]
}
I will try this later, thanks
user Q
Most welcome, (Removed Name), and glad you saw into it :)
Hey ! just to confirm I was on the right path, this works like a charm (js client)
writeClient.patch(<documentID>)
        .setIfMissing({
            [`entries[_key==\"${entryId}\"].subentries`]: []
        })
        .append(`entries[_key==\"${entryId}\"].subentries`, [{
            _key: uuid(),
            ...=> data here
        }])
        .commit()
Good man :) Looks like you covered the angles nicely, and this will be good for others to find. Take care, (Removed Name), (Removed Name) (we're having a long weekend over here, so things will be quiet)

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?