Find documents referencing a specific schema as a block

9 replies
Last updated: Sep 20, 2022
I’m deprecating a component. Is there an easy way to find all documents which reference a specific schema as a block?
AI Update

Great question! When deprecating a custom block component in Portable Text, you'll want to find all documents that still use it. Here's how you can do that with GROQ:

*[content[]._type == "yourDeprecatedBlockType"]

This searches through all documents and checks if any items in the content array (your Portable Text field) have a _type matching your deprecated block.

More specific examples:

If you want to see which documents are affected and get some context:

*[content[]._type == "yourDeprecatedBlockType"]{
  _id,
  _type,
  title,
  "blockCount": count(content[_type == "yourDeprecatedBlockType"])
}

This returns the document ID, type, title, and counts how many instances of that block appear in each document.

For nested Portable Text:

If your custom block might be nested deeper (like inside another object in the array), you can use:

*["yourDeprecatedBlockType" in content[]._type]

Multiple field names:

If your Portable Text field isn't always called content, you can check multiple fields:

*[
  body[]._type == "yourDeprecatedBlockType" || 
  content[]._type == "yourDeprecatedBlockType" ||
  description[]._type == "yourDeprecatedBlockType"
]

You can run these queries in Sanity's Vision plugin (right in your Studio) or use the JavaScript client to run them programmatically. The Vision plugin is especially handy for this kind of exploratory work since you can iterate on your query quickly and see results immediately.

Once you've identified all the documents, you can either manually update them in Studio or write a content migration script to bulk-update or remove the deprecated blocks.

Show original thread
9 replies
There is! You can find it using:
*[references(<id-of-document>)]
.
Though, I'm unclear from your question whether the component you're deprecating is a document you're referencing, some schema that isn't a document, or a schema inside of block content. That query will only work if it's a reference to a document.
Sorry, for being unclear. The schema is for an object not a document.
e.g. find all documents that use the custom form block.
No worries, just wanted to make sure I'm giving you relevant information.
Does that object always have the same name when you use it in your schema? If so, something like
*[defined(<name-of-field>)]
should get it for you. If that's not the case, I"m afraid there's not an easy way to find each place it's used.
thx, and where would you be executing that query?
The schema looks roughly like this:
{
title: 'body',
type: 'array',
of: [
 { type: block, .... },
 { type: 'custom-form'},
 { ... ~100 components }
]
}
I usually write a JS script that I can use to batch remove a field that performs that query. Here's an example:
import { studioClient } from './studioClient';
import cq from 'concurrent-queue';

// Create a queue to limit the rate at which you write changes to Sanity
let queue = cq()
  .limit({ concurrency: 25 })
  .process(task => {
    return new Promise(function (resolve, reject) {
      setTimeout(resolve.bind(undefined, task), 1000);
    });
  });

const mutateDocs = async () => {
  //Fetch the documents you need to mutate
  const query = `*[defined(<name-of-field>)]`;
  const docs = await studioClient.fetch(query);
  // Loop through all of the docs returned from our query
  for (const doc of docs) {
    queue(doc).then(async () => {
      // Add a message to help us know the upload is happening
      console.log(`Mutating ${doc._id}`);
      // Tell the client to patch the current document
      studioClient
        .patch(doc._id)
        // Unset the field
        .unset(['<name-of-field>'])
        // Commit the changes
        .commit()
        .then(updatedDoc =>
          console.log(`Hurray, the doc is updated! New document:`, updatedDoc)
        )
        .catch(err => console.error('Oh no, the update failed: ', err.message));
    });
  }
};

mutateDocs();

// execute this script by running
// $ sanity exec ./lib/utils/mutateDocs.js --withUserToken
It looks like you're using that custom-form inside of block content, so your query will need to be more complicated than just using the
defined
function. You'll probably need to do something like
*['custom-form' in body[]._type]
.
Your patch will also have to be more complicated than my example.
k, thanks for the pointers

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.

Was this answer helpful?