Filter GROQ query by array of referenced category names

36 replies
Last updated: Nov 29, 2025
Hello!
I have some blog posts I am trying to fetch

but I want to filter them by their category.

Categories is an array of references.

I am not sure how to construct the GROQ query to filter an item by a reference matching a name within the reference.

I am constructing some sort of conditional filter on a GROQ query and was wondering if this makes sense? I do not think it works


export const getPublishedBlogPosts = (
  categories: Array<String>
) => `*[_type == "post" && published == true ${
  categories ? `&& categories[]->title [@ in ${categories.join(", ")}]` : ""
}] | order(updatedNewestFirst) {
  categories[]-> {
    title
  },
  author-> {
    name,
    title,
    image,
    slug,
  },
  type,
  slug,
  title,
  description,
  mainImage,
}`;
Which I am calling like


export const getServerSideProps = async () => ({
  props: {
    posts: await sanity.fetch(getPublishedBlogPosts(["Freelance Writing"])),
  },
});
this seems like it would work but I get some errors.


expected ']' following expression
which does not seem right as i add the
]
following the ternary
I tried basing it off the cheatsheet examples.
AI Update

I can help you fix that GROQ query! The issue is with the syntax of your filter condition. You're close, but the way you're checking if dereferenced category titles match your array needs adjustment.

Here's the corrected version:

export const getPublishedBlogPosts = (
  categories: Array<String>
) => `*[_type == "post" && published == true ${
  categories.length > 0 ? `&& categories[]->title in [${categories.map(c => `"${c}"`).join(", ")}]` : ""
}] | order(updatedNewestFirst) {
  categories[]-> {
    title
  },
  author-> {
    name,
    title,
    image,
    slug,
  },
  type,
  slug,
  title,
  description,
  mainImage,
}`;

The problems with your original query:

  1. The syntax categories[]->title [@ in ${categories.join(", ")}] is malformed
  2. You're not wrapping the string values in quotes - GROQ needs ["Freelance Writing"] not [Freelance Writing]
  3. The @ operator isn't needed here for a simple in check

What the fix does:

  • categories[]->title - dereferences all category references in the array and gets their title field
  • in [...] - checks if any of those titles exist in your provided array
  • ${categories.map(c => "${c}").join(", ")} - properly formats your JavaScript array into a GROQ array with quoted strings

So when you call:

posts: await sanity.fetch(getPublishedBlogPosts(["Freelance Writing"]))

The resulting GROQ filter becomes:

&& categories[]->title in ["Freelance Writing"]

This will match any post where at least one of its category references has a title of "Freelance Writing".

Alternative approach using count:

If you prefer being more explicit, you can also use:

const categoryFilter = categories.length > 0
  ? `&& count((categories[]->title)[@ in [${categories.map(c => `"${c}"`).join(", ")}]]) > 0`
  : "";

This filters the dereferenced titles to only those in your array, counts them, and checks if the count is greater than 0. Both approaches work, but the in operator is simpler and more readable.

Show original thread
36 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?