Help with GROQ join in Sanity.io for searching products by category.
Welcome to Sanity! Great question - GROQ joins can be tricky at first, but once you get the hang of references, they're quite powerful.
The issue with your query is that you're trying to do the join "backwards." Instead of nesting another query inside, you want to dereference the category references and then filter the products based on those dereferenced values.
Here's the corrected approach:
*[_type == "product" && "swedish" in categories[]->slug.current] {
...,
"categories": categories[]->{
_id,
title,
slug
}
}Let me break down what's happening:
categories[]->slug.current- The->operator dereferences the array of category references, following them to get the actual category documents, then accesses theirslug.currentfield"swedish" in categories[]->slug.current- This checks if "swedish" exists in the array of dereferenced category slugs (theinoperator is perfect for array matching)"categories": categories[]->{...}- This expands the category references in your projection to include the full category data instead of just references
If you want to search by category name instead of slug, you can use:
*[_type == "product" && "Swedish" in categories[]->title]Alternative using references(): If you already know the category's _id, you can use the references() function:
*[_type == "product" && references(*[_type == "category" && slug.current == "swedish"]._id)]The Sanity GROQ recipe on filtering by category has great examples of this pattern. The key thing to remember is that the in keyword is used to find matches in an array, and the -> operator dereferences your array of category references so you can access their properties.
You can also check out the GROQ Query Cheat Sheet for more examples of working with references and arrays!
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.