GROQ query: Filter documents where array field intersects with parameter array

4 replies
Last updated: Nov 29, 2025
Hi,
I have this blog page, that displays links to other similar blogs. The similarity is based on category, where every blog can have multiple string categories. So basically, in a blog that has ["Design", "Research"] categories, I need to display links to blogs with either "Design" or "Research" category. Note that they can have other categories as well.
I have this small query that works only with 1 category. Can somebody help me achieve the intersection of categories between fetched blogs?


`*[_type == 'blog' && $category in categories] {
      _id,
      _updatedAt,
      categories,
      description,
      title,
      timeToRead,
      publishedAt,
    }`,
    {
      category,
    }
Instead of
_type == 'blog' && $category in categories
I need something like
_type == 'blog' && ($category *has any in* categories)
where
$category
is also an array.
Thanks.
AI Update

Perfect! I found the exact solution to your problem. The trick is to use the count() function combined with the @ filter operator to check if any elements from one array exist in another array.

Here's how to solve your problem:

*[_type == 'blog' && count(categories[@ in $categories]) > 0] {
  _id,
  _updatedAt,
  categories,
  description,
  title,
  timeToRead,
  publishedAt,
}

Where $categories is your array parameter (e.g., ["Design", "Research"]).

How it works:

The expression categories[@ in $categories] filters the categories array to only include elements that exist in your $categories parameter array. Then count() counts how many matches there are. If the count is greater than 0, it means at least one category matches, and that blog post is included in the results.

Example:

  • If a blog has categories: ["Design", "UX", "Frontend"]
  • And you pass $categories: ["Design", "Research"]
  • The expression categories[@ in $categories] evaluates to ["Design"]
  • count(["Design"]) returns 1
  • Since 1 > 0, this blog is included in results

This is exactly the "array intersection" check you need! The @ symbol in GROQ represents the current element being iterated over, and the in operator checks if that element exists in the comparison array.

This pattern comes from this community discussion about comparing arrays and checking for string overlap in GROQ queries, which is exactly your use case.

You can test this in Vision (Sanity's query testing tool) with your parameters to verify it works as expected!

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