Patches
The valid patch types when using the direct HTTP mutations api.
It is good practice to use patches when modifying Sanity documents through the API. Ideally, you make the smallest, most specific patch possible for your changes so that if multiple scripts or users are modifying the same documents at the same time, Sanity is able to merge those changes in a sensible way.
A patch is a special mutation submitted through the mutations API endpoint. Since this endpoint is transactional you may submit one or several patches at once, potentially changing any number of documents in one single transaction. Here is an example of a full transaction submitting two patches at once (This sets the name property of the document with id "person-123" to "Remington Steele" and adds a reference to it to the end of the people-array of the document with the id "remingtons":
{
"mutations": [
{
"patch": {
"id": "person-1234",
"set": {
"name": "Remington Steele"
}
}
},
{
"patch": {
"id": "remingtons",
"insert": {
"after": "people[-1]",
"items": [
{
"_type": "reference",
"_ref": "person-1234"
}
]
}
}
}
]
}
Note: Generally the keys of the patches use JSONMatch syntax to target values for change. This syntax generally allows for paths like some.array[8].attribute
, but can also do pattern matching, recursive search, and target multiple values at once. The full syntax is documented here.
Protip
JSONMatch
is a variant of JSONPath
that simplifies the syntax and eliminating to the maximum extent the number of special characters required to express a path.
set
performs a shallow merge of its argument into the document. Each key in the argument is either an attribute or a JSON path.
{ "set": { attributeOrJSONPathExpression: any } }
Object properties
Set the field name
to the value Bob
and the nested field personalMetrics.height
to 201
:
{ "set": { "name": "Bob", "personalMetrics.height": 201 } }
Arrays
Set the text
property to the value Do the thing!
in all objects in the body
array where the _type
is cta
:
{ "set": { "body[_type==\"cta\"].text": "Do the thing!" } }
Gotcha
Notice that the array filter ([_type == \"cta\"]
) must use double quotes. If you are in JSON, you must escape them (\"
).
setIfMissing
is like set
, except existing keys will be preserved and not overwritten.
Deletes one or more attributes. Each entry in the argument is either an attribute or a JSON path. Missing attributes are ignored. Unset can also be used to delete elements of an array.
{ "unset": [ attributeOrJSONPathExpression, ... ] }
{ "unset": ["foo", "bar"] }
insert
provides methods for modifying arrays, by inserting, appending and replacing elements via a JSONPath expression.
Inserts the string "a"
at the end of the array some.array:
{
"insert": {
"after": "some.array[-1]",
"items": ["a"]
}
}
Inserts the string "a"
at index 2 before whatever was there:
{
"insert": {
"before": "some.array[2]",
"items": ["a"]
}
}
This inserts the string "a"
at the beginning of the array.
{
"insert": {
"before": "some.array[0]",
"items": ["a"]
}
}
This removes index 2 through the end of the array, replacing the content with "a"
.
{
"insert": {
"replace": "some.array[2:]",
"items": ["a"]
}
}
NOTE: see the article on JSONMatch for more details
Finds the element that has key == 'abc-123'
and inserts "a"
after it.
{
"insert": {
"after": "some.array[key == \"abc-123\"]",
"items": ["a"]
}
}
Finds any object that has key == 'list-123'
adds "a"
at the beginning of its items array:
{
"insert": {
"before": "blocktext..[key=\"list-123\"].items[0]",
"items": ["a"]
}
}
Gotcha
Since single quotes are used to denote field names, regular strings must be enclosed in double quotes. When defining patches in JSON, the double quotation marks needs to be escaped (\"
).
inc
and dec
change a numeric value. Each entry in the argument is either an attribute or a JSON path. For each entry, the attribute is looked up, modified and stored. The value may be a positive or negative integer or floating-point value. The operation will fail if target value is not a numeric value, or doesn't exist.
inc
increments; dec
is the same as inc
, except the value is decremented.
{
"inc": {
"stats.visitorCount": 1
}
}
If it's not certain whether the attribute exists, you can provide a default with setIfMissing
:
{
"setIfMissing": {
"stats.visitorCount": 0
},
"inc": {
"stats.visitorCount": 1
}
}
This operation supports robust incremental text patches according to the Google diff-match-patch algorithm, which has wide library support in practically all programming languages in common use. Given the document:
{
"_id": "dog-1",
"_type": "someType",
"aboutADog": "The rabid dog"
}
The following patch applies a diff-match-patch patch to the string:
{
"patch": {
"id": "dog-1",
"diffMatchPatch": {
"aboutADog": "@@ -1,13 +1,12 @@\n The \n-rabid\n+nice\n dog\n"
}
}
}
The document is transformed to read:
{
"_id": "dog-1",
"_type": "someType",
"aboutADog": "The nice dog"
}
The beauty of diff-match-patch patches is that they allow you to modify huge strings with small patches, and that they compose well, generally giving sane results even when several users or scripts are modifying the same text.