Migrating data from old to new field using Sanity's Patches API
Great question! This is a perfect use case for Sanity's migration tooling. You'll want to use the defineMigration API to programmatically copy the Body field from your referenced Content documents into the new Body field on your main documents.
Step 1: Create the Migration Script
First, generate a new migration:
npx sanity@latest migration create "Copy body from content reference"Step 2: Write the Migration Logic
In the generated index.ts file, you'll need to:
- Fetch the referenced Content document using GROQ
- Extract the Body field from it
- Copy it to the new Body field on the main document
Here's what the migration script should look like:
import {defineMigration, at, set} from 'sanity/migrate'
export default defineMigration({
title: 'Copy Body from Content reference to new Body field',
documentTypes: ['yourDocumentType'], // Replace with your document type
migrate: {
async document(doc, context) {
// Check if Content reference exists and new Body doesn't
if (doc.Content?._ref && !doc.Body) {
try {
// Fetch the referenced Content document using GROQ
const contentDoc = await context.client.fetch(
`*[_id == $refId][0]{ Body }`,
{ refId: doc.Content._ref }
)
// If the Content document has a Body field, copy it
if (contentDoc?.Body) {
return [
at('Body', set(contentDoc.Body))
]
}
} catch (error) {
console.error(`Failed to fetch content for doc ${doc._id}:`, error)
}
}
// Return empty array if no changes needed
return []
}
}
})The key difference from typical Sanity Client usage is that within migrations, you use context.client.fetch() with GROQ queries to retrieve data. This is the documented pattern as shown in this recipe for updating references.
Step 3: Test with Dry Run
Always test first without making changes:
sanity migration run "Copy body from content reference"This will show you what changes would be made without actually modifying your data.
Step 4: Execute the Migration
Once you're satisfied with the dry run results, execute it on your dataset:
sanity migration run "Copy body from content reference" --dataset <your-dataset-name>Important Considerations
Graceful error handling: The script includes try-catch blocks because migration scripts should handle failures gracefully, especially with large datasets where some references might be broken or missing.
Idempotent design: The script checks if
doc.Bodyalready exists before copying, making it safe to run multiple times without duplicating data.Performance: The migration tool automatically batches mutations to avoid rate limits, which is helpful for your 1000+ posts.
Backup: Consider backing up your dataset before running the migration on production data.
If you need to handle more complex scenarios (like merging content or transforming the Body field during the copy), you can add additional logic within the document transformation function. The content migration documentation has more examples of advanced transformations.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.