Saskia Bobinska
Senior Support Engineer @Sanity
Use a migration script to update all references from one document to another
import { isEqual } from 'lodash'
import { defineMigration, set } from 'sanity/migrate'
// ! change these to your values
const title = 'This is an old page title'
const newTitle = 'This is your new page title'
const refType = 'page'
export default defineMigration({
title: `Change references from "${title}" to "${newTitle}"`,
// ! change this to your document types
documentTypes: [ 'page', 'article', 'settings' ],
migrate: {
// first we need to define which method we want to use (string, array, object, etc) -> since we need to fetch the old and new doc Ids it is async
async string(node, path, context) {
// first configure the correct client and make sure we get the "normalised" IDs (no drafts)
const client = context.client.withConfig({ perspective: 'previewDrafts' })
let oldReferenceId: string | null = null
let newReferenceId: string | null = null
try {
// fetch the old reference ID from the old title
const oldReference = await client.fetch(
`*[_type == "${refType}" && title == "${title}"][0]._id`,
)
oldReferenceId = oldReference
// fetch the new reference ID from the new title
const newReference = await client.fetch(
`*[_type == "${refType}" && title == "${newTitle}"][0]._id`,
)
newReferenceId = newReference
} catch (error) {
console.error('Error fetching documents', error)
}
// migrate all document with the old reference to the new reference ID
if (node === oldReferenceId && !isEqual(path, ['_id'])) {
return set(newReferenceId)
}
},
},
})
A common use case for migration scripts is changing one value for another, especially updating all references that point to one document (old Doc) to reference a new one.
The good thing about Migration scripts is that they will find each reference field you have, no matter how deeply nested, without you needing to know each path.
If you know the old and new IDs that should be changed, you can actually use a similar approach to this example in our documentation.
But let's say you do not know the IDs, only the titles for your old and new documents; your migration script will not be as straightforward. My example is only one option (you could also iterate through all object
nodes that have a _ref
value, for example), but it will show how you can combine async data fetching and substituting one _ref
value for another.
Make sure to read the introduction and important consideration articles about migration scripts.
The documentation contains instructions on how to (dry) run Migration scripts.
Changes made via these scripts cannot be reversed in bulk, so make sure to read the documentation closely first.
Pro Tip:
Depending on your dataset size, you can use the async generator pattern to deduce the number of documents loaded into memory (see docs).
Senior Support Engineer @Sanity
If you install plugins or other packages with conflicting (peer) dependencies, you can use this useful workaround to unblock yourself.
Go to What to do when Studio crashes due to conflicts in dependency versions?When creating custom document actions, it can be necessary to check, wether all validation rules are full-filled.
Go to Use the validation status of a document in your custom document actionsOnly return a value when a condition is fulfilled
Go to Conditional values in GROQ queriesIf you want to make it possible to use parameterised initialValue templates in reference fields, this is how!
Go to Create a new reference document with parameterised initial Values