
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeGreat 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.
First, generate a new migration:
npx sanity@latest migration create "Copy body from content reference"In the generated index.ts file, you'll need to:
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.
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.
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>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.Body already 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 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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store