Writing a content migration

While the current solution with the adapted GROQ query and the deprecated field works, having two field names for the same type of content can be confusing. Imagine you want to make a new filter on the home page. You would have to take both field names into account. For changes like these, it might be a good idea to move the legacy content over to the new field and, in this case, remove the old field completely so we can also keep the document form nice and tidy.
Since the front end query now works with both fields, you can even migrate content against the production dataset without any downtime or disruption.
The Sanity CLI contains helpful guidance and templates to create content migration scripts.
# in apps/studionpx sanity@latest migration create Replace event type with event formatThe CLI will prompt with some questions; answer the following (you can always change this in code after):
The CLI should now have made a new folder in your Studio project called migrations with a content migration script inside replace-event-type-with-event-format/index.ts.
In fact, the CLI has done most of the job already. But let’s unpack what’s going on.
import {defineMigration, at, setIfMissing, unset} from 'sanity/migrate'
const from = 'oldFieldName'const to = 'newFieldName'
export default defineMigration({ title: 'Replace event type with event format', documentTypes: ["event"],
migrate: { document(doc, context) { return [ at(to, setIfMissing(doc[from])), at(from, unset()) ] } }})You can see that the script imports a couple of functions from sanity/migrate and has a default export called defineMigration.
Change the from and to variables to reflect the schema change you want to do.
from to the value eventTypeto to the value formatimport {defineMigration, at, setIfMissing, unset} from 'sanity/migrate'
const from = 'eventType'const to = 'format'
export default defineMigration({ title: 'Replace event type with event format', documentTypes: ["event"],
migrate: { document(doc, context) { return [ at(to, setIfMissing(doc[from])), at(from, unset()) ] } }})What happens when you run this, is that it will fetch all the documents of the type event and then export two patches for that document:
- the
at(to, setIfMissing(doc[from]))patch sets a new field calledformatwith the value of theeventType,setIfMissingensures that the value is set only ifformatdoesn’t exist from before at(from, unset())removes theeventTypevalue, and thus the field from the document
Save your changes. If you run npx sanity@latest migration list. You should get a table with the migration ID and title:
# in apps/studionpx sanity@latest migration list