GROQ: Query array with multiple document types and different projections

25 replies
Last updated: Jan 28, 2026
Hi everyone, I've got another question for the groq masters.
I'm not sure how to query an array that contains more than one document type. My schema is as follows:

export default {
  title: "Resources",
  name: "resourcesPage",
  type: "document",
  __experimental_actions: [/*'create',*/ "update", /*'delete',*/ "publish"],
  fields: [
    mainHeading(),
    subHeading(),
    bodyTextNormal(),
    {
      title: "Resource Items",
      name: "resourceItems",
      type: "array",
      of: [
        {
          type: "reference",
          name: "youTube",
          title: "YouTube Video",
          to: {
            type: "youTube",
          },
        },
        {
          type: "reference",
          name: "blogPost",
          title: "Blog Post",
          to: {
            type: "blogPost",
          },
        },
      ],
    },
  ],
};
When I query the array:

*[_type == "resourcesPage" ][0] {
      resourceItems[]->
}
I get (cleaned up and commented):

{
  "resourceItems": [
    // First array item - a summary of a YouTube video
    {
      "_createdAt": "2021-11-06T03:52:16Z",
      "_id": "57b5415a-c03f-43b8-9f8d-e9e494740e91",
      "_rev": "65Id4bytofoxKzz3lRg5RP",
      "_type": "youTube",
      "_updatedAt": "2021-11-06T03:52:16Z",
      "description": "The description text",
      "thumbnail": "<https://i.ytimg.com/vi/k2Vyjj1j_eY/maxresdefault.jpg>",
      "title": "The title",
      "url": "<https://www.youtube.com/watch?v=xxxxxxxx>"
    },

    // Second array item - a blog post
    {
      "_createdAt": "2021-11-08T00:55:59Z",
      "_id": "e3c0f198-60cd-4613-8fdb-4735115bbaaa",
      "_rev": "yuZxWYwFNB6KJB4TNpS46C",
      "_type": "blogPost",
      "_updatedAt": "2021-11-08T02:17:31Z",
      "author": {
        "_ref": "5f618def-ec87-4dad-adfa-0a704a7a48d4",
        "_type": "reference"
      },
      "body": [
        // Portable text here
      ],
      "mainImage": {
        "_type": "image",
        "altText": "The alt text",
        "asset": {
          "_ref": "image-XXXXXXXXXX-5760x3840-jpg",
          "_type": "reference"
        }
      },
      "publishedDate": "2021-11-08T00:51:00.000Z",
      "slug": {
        "_type": "slug",
        "current": "test-blog-post"
      },
      "subtitle": "This Is A Test Blog Post",
      "tags": [
        {
          "_key": "d14e12e4c705",
          "_ref": "994dea5e-08be-4d85-9cf1-443f03191cc5",
          "_type": "reference"
        },
        {
          "_key": "45fcec2de5d0",
          "_ref": "489d2487-ffa3-48f4-a98a-b3ead02ff912",
          "_type": "reference"
        }
      ],
      "title": "Test Blog Post"
    }
  ]
}
I have no problem dealing with an array of one document type, but I can't figure out the groq syntax to add the two different projections to pull what I need from the different document types in the array.
AI Update

Good question! When you have an array with references to different document types, you need to use conditional projections in GROQ to handle each type differently.

The key is using the _type field to conditionally project different fields based on the document type. Here's how you'd modify your query:

*[_type == "resourcesPage"][0] {
  resourceItems[]-> {
    _type == "youTube" => {
      _id,
      _type,
      title,
      description,
      url,
      thumbnail
    },
    _type == "blogPost" => {
      _id,
      _type,
      title,
      subtitle,
      slug,
      publishedDate,
      mainImage {
        altText,
        asset->
      },
      author->,
      tags[]->
    }
  }
}

The syntax _type == "youTube" => { ... } is a conditional projection that only applies when the condition is true. You can chain multiple conditions for each document type in your array.

If you want to include some common fields for all types plus type-specific fields, you can combine this with the ellipsis operator (...):

*[_type == "resourcesPage"][0] {
  resourceItems[]-> {
    ...,
    _type == "youTube" => {
      "videoUrl": url,
      "videoThumbnail": thumbnail
    },
    _type == "blogPost" => {
      "postSlug": slug.current,
      "postImage": mainImage.asset->url,
      author->
    }
  }
}

The ... includes all fields from the referenced document, and then the conditional projections add or override specific fields based on the type. Note that the ellipsis is always evaluated first regardless of position, so any fields you define after will override the original values if they have the same name.

This pattern works great for heterogeneous arrays and gives you full control over what data you fetch for each document type!

Show original thread
25 replies

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?