Filter GROQ query by array of referenced category names
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,
}`;export const getServerSideProps = async () => ({
props: {
posts: await sanity.fetch(getPublishedBlogPosts(["Freelance Writing"])),
},
});expected ']' following expression]following the ternary
I tried basing it off the cheatsheet examples.
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:
- The syntax
categories[]->title [@ in ${categories.join(", ")}]is malformed - You're not wrapping the string values in quotes - GROQ needs
["Freelance Writing"]not[Freelance Writing] - The
@operator isn't needed here for a simpleincheck
What the fix does:
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 thread36 replies
Was this answer helpful?
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.