Is there a way to write a groq query that checks if a boolean is true, and if so, returns an array of referenced documents? (example use case, on a homepage, I want to allow...

7 replies
Last updated: Feb 1, 2021
Is there a way to write a groq query that checks if a boolean is true, and if so, returns an array of referenced documents? (example use case, on a homepage, I want to allow the client to enable/disable showing the 3 most recent blog posts)I have this, but it doesn’t work

{ features[_type match 'blogEntries'] { 'posts' : *[_type == 'post'][0..2] { ... } } }

AI Update

You can use the select() function in GROQ to conditionally return an array based on a boolean value. The select() function works like a switch statement and evaluates conditions in order, returning the first matching value.

For your use case of showing/hiding the 3 most recent blog posts based on a boolean, here's how to structure it:

*[_id == "homepage"][0] {
  ...,
  "posts": select(
    showBlogPosts == true => *[_type == 'post'] | order(publishedAt desc) [0..2] {
      title,
      slug,
      publishedAt
    },
    []
  )
}

This query:

  • Checks if showBlogPosts is true
  • If true, returns an array of the 3 most recent posts
  • If false (or undefined), returns an empty array []

You can also use a more concise version if your boolean field might be undefined:

*[_id == "homepage"][0] {
  ...,
  "posts": select(
    defined(showBlogPosts) && showBlogPosts => *[_type == 'post'] | order(publishedAt desc) [0..2] { ... },
    []
  )
}

The key differences from your original attempt:

  1. Use the select() function with a condition-value pair syntax: condition => value
  2. The condition checks your boolean field directly
  3. Provide a fallback value (empty array) when the condition is false
  4. The entire subquery goes after the => arrow

You can also use this pattern within projections if you have multiple features to toggle:

*[_id == "homepage"][0] {
  title,
  "blogSection": select(showBlogPosts => {
    "posts": *[_type == 'post'] | order(publishedAt desc) [0..2] { ... }
  }),
  "newsSection": select(showNews => {
    "items": *[_type == 'news'] | order(_createdAt desc) [0..5] { ... }
  })
}

This gives your clients flexible control over which content sections appear on the homepage!

I think I got it
{
  "posts": *[_type == 'post' && 'blogEntries' in (^.features[]._type)][0..2],	
} 
I guess the question now is, can I modify the limit based on a field value. Ie, inside of ‘blogEntries’ if I set the query to return 5 instead of three, can I make that range at the end become [0..4] ?
If you pass the end number as a parameter, you could replace
[0..2]
with something like
[0..$num]
.
Could $num somehow be referenced from the query response
Yes, $num would be a query parameter that you could pass through the URI, as props, or even pulling from a document containing the ranges.
Here’s an example:

export async function getAllStaff(num) {
  const result = await client.fetch(
    `*[_type == "staff"] | order(firstName asc, lastName asc) {
      firstName,
      lastName,
      slug,
      image,
      position,
      _type,
    }[0..${num}]`
  );

  return result;
}
Then I’m calling the function from getStaticProps and passing in `num`:


export async function getStaticProps() {
  const allStaff = await getAllStaff(8);

  return {
    props: { allStaff },
    revalidate: 120,
  };
}

Thanks
user A
, that looks great

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?