Query multiple document types with conditional projections returning null

11 replies
Last updated: Mar 7, 2022
Hey all, I'm trying to grab data from two different documents with one query. From my understanding of the documentation this should be possible by doing something like
// Specify sets of projections for different content types in an array
content[]{
  _type == 'type1' => {
    // Your selection of fields for type1
  },
  _type == 'type2' => {
    // Your selection of fields for type2
    "url": file.asset->url // Use joins to get data of referenced document
  }
}
However, when I do this I get
null
I'll put my actual queries in the comments.Thanks,
AI Update

Looking at your query, you're very close! The syntax you're trying to use is correct - conditional projections with the _type == 'value' => pattern is indeed the right approach for querying arrays with multiple document types.

Based on the example from the Query Cheat Sheet, here's the correct syntax:

*[_type == "resourcesPage"][0] {
  mainHeading,
  subHeading,
  bodyText,
  resourceItems[]-> {
    _type == "youTube" => {
      _type,
      title,
      url,
      description,
      thumbnail
    },
    _type == "blogPost" => {
      _type,
      title,
      summary,
      mainImage,
      author->{ name, avatar },
      "tags": tags[]-> tagName,
      "slug": slug.current
    }
  }
}

The key points about conditional projections:

  1. Use the arrow operator (->) to follow the references first: resourceItems[]->
  2. Then add conditional projections inside the projection block using _type == 'value' => { fields }
  3. Each condition returns only the specified fields for that document type
  4. This preserves the original array order (no need for sorting plugins!)
  5. No null values are returned for missing fields

This approach is much cleaner than:

  • Separating into multiple arrays and concatenating on the frontend
  • Including all fields and getting nulls for non-existent fields
  • Using ordering plugins to maintain sequence

The conditional projection syntax gives you exactly what you need: an array of mixed document types, each with their own specific fields, in the original order. This is part of GROQ's projection features that allow you to transform and reshape data based on conditions.

If you're getting null as a result, double-check that:

  • Your resourceItems array actually contains references (has _ref values)
  • The referenced documents exist and have the _type values you're checking for
  • You're using the dereference operator -> correctly

You can test this step-by-step in Vision by first querying just resourceItems[]-> to see what the dereferenced documents look like, then adding the conditional projections.

Show original thread
11 replies
So, to get the data individually I can do

*[_type == "collections" && publish == true] {
    heading,
    heroImage,
    slug,
    featured,
  }
and

*[_type == "marketing_pages" && slug.current == "collections"]{
   seo_title,
   seo_desc,
   page_builder,
   
 }
which both work on their own
but something like this doesn't work
content[]{
  _type == "collections" && publish == true] => {
    heading,
    heroImage,
    slug,
    featured,
  },
  _type == "marketing_pages" && slug.current == "collections" => {
   seo_title,
   seo_desc,
   page_builder,
  },
}

The example you have above is for conditionally rendering fields within a document. To combine queries you can do it like this:
{
  "first": *[_type == "collections" && publish == true] {
    heading,
    heroImage,
    slug,
    featured
  },
  "second": *[_type == "marketing_pages" && slug.current == "collections"] {
    seo_title,
    seo_desc,
    page_builder
  }
}
ahhhh
Thanks so much!!!
No problem
but something like this doesn't work
content[]{
  _type == "collections" && publish == true] => {
    heading,
    heroImage,
    slug,
    featured,
  },
  _type == "marketing_pages" && slug.current == "collections" => {
   seo_title,
   seo_desc,
   page_builder,
  },
}

The example you have above is for conditionally rendering fields within a document. To combine queries you can do it like this:
{
  "first": *[_type == "collections" && publish == true] {
    heading,
    heroImage,
    slug,
    featured
  },
  "second": *[_type == "marketing_pages" && slug.current == "collections"] {
    seo_title,
    seo_desc,
    page_builder
  }
}
ahhhh
Thanks so much!!!
No problem

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?