Lesson
5
Writing a content migration
Use Sanity CLI to create a new content migration. Adapt the migration script for your use case.
Log in to mark your progress for each Lesson and Task
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.
Inside your Sanity Studio, create a new content migration
npx sanity@latest migration create "Replace event type with event format"
The CLI will prompt with some questions; answer the following (you can always change this in code after):
Type of documents to migrate: event
Select a template: Rename a field
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
.
Open the content migration script in your code editor
In fact, the CLI has done most of the job already. But let’s unpack what’s going on.
migrations/replace-event-type-with-event-format/index.ts
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.
Set
from
to the value eventType
Set
to
to the value format
migrations/replace-event-type-with-event-format/index.ts
import {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 calledformat
with the value of theeventType
,setIfMissing
ensures that the value is set only ifformat
doesn’t exist from before at(from, unset())
removes theeventType
value, 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:
Run
npx sanity@latest migration list
and copy the content migration IDYou have 7 uncompleted tasks in this lesson
0 of 7