skip to content
Headshot of Cole Townsend wearing a yellow sweater

Cole Townsend, Software Designer

How to Do Bulk Updates with References in Sanity

I had a hard time figuring out how to handle bulk updates (patches) for articles in Sanity. While there is documentation about modifying general arrays and text fields, there was nothing about modifying related fields in bulk.

Through a bit of trial and error I figured out that it was relatively similar to a create call.

The safest way to make a bulk update is using transactions. Set up your async function with by calling sanityClient.transaction(). You can then chain all your patch modifications together thanks to the Sanity client.

transaction.patch(article._id, (p) => {
return p.insert("after", "tags[-1]", [ITEM_REF]);
});

In the snippet above I am adding a predefined relational reference at the end of the array field.

Commonly you won’t need to modify all of your articles. Below is a simple example of how you can tag articles containing a keyword by running a patch transaction using the Sanity client.

sanityClient.ts
import { createClient } from "@sanity/client";
const sanityClient = createClient({
projectId: "<YOUR_PROJECT_ID>",
dataset: "production", # this may change depending on what you named it
useCdn: false,
apiVersion: "2023-09-28",
token:
"<YOUR TOKEN HERE>",
});
export default sanityClient;

Now import the Sanity client.

transform.ts
import sanityClient from "./sanityClient";
const ITEM_REF = {
_type: "reference",
_ref: "<YOUR_REF_ID>", # replace with your ID string from Sanity.
};
interface Article {
content: any[];
_id: string;
tags: string[];
}
const updateArticles = async (articlesToUpdate: Article[]) => {
const transaction = sanityClient.transaction();
articlesToUpdate.forEach((article: any) => {
transaction.patch(article._id, (p) => {
return p.insert("after", "tags[-1]", [ITEM_REF]);
});
});
try {
const result = await transaction.commit({
autoGenerateArrayKeys: true,
});
console.log("Transaction committed:", result);
} catch (error) {
console.error("Transaction failed:", error);
}
};
const runUpdate = async () => {
try {
// Get all articles from sanity
const articles: Article[] = await sanityClient.fetch(
`*[_type == "article" && title match ['My Keyword**']] {
_id,
title,
tags[]->{
_id,
name,
"slug": slug.current
},
} | order(updatedDate desc, publishedAt desc)`
);
let articlesToUpdate: Array<Article> = [];
articles.forEach((article: any) => {
if (
article &&
article.tags &&
article.tags.length &&
article.tags.every((tag: any) => tag.slug !== "target-slug")
) {
articlesToUpdate.push(article);
}
});
await updateArticles(articlesToUpdate);
} catch (error) {
console.error(error);
}
};
runUpdate();

Running the Update with TS Node Dev

To run this, you could set up a simple typescript project. Run ts-init and install the necessary dependencies, namely the Sanity client.

package.json
{
"name": "sanity-update",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^20.9.0",
"typescript": "^5.2.2"
},
"dependencies": {
"@sanity/client": "latest",
}
}

Run npx ts-node transform.ts and your articles will be updated using a Sanity client patch transaction.