GROQ Query - Is it Possible to Filter Variants?
I can see the issue! The problem is with how you're chaining your filter operations after dereferencing. The pipe operator | expects an object or function (like order() or a projection), but you're trying to use a filter [variantId in $variantIds] directly after it.
The syntax variants[]->|[variantId in $variantIds] is invalid because after the pipe operator, GROQ expects a projection {} or a function like order(), not a filter [].
Here's the corrected syntax:
*[_type == "product" && _id in $ids]
{
price,
"variant": variants[]->[variantId in $variantIds][0]{
packageSize,
flavour,
variantId,
},
"image": images[defaultImage == true][0]{
altText,
"url": asset->url
}
}Key changes:
- Remove the pipe operator
|between->and the filter - The syntax is:
variants[]->(dereference all) then[variantId in $variantIds](filter) then[0](take first) then{...}(project)
Why this works:
According to the GROQ pipeline components documentation, filters use [] syntax and can be chained directly without the pipe operator. The pipe operator is specifically required for certain operations like order() and is optional for projections, but filters must be adjacent to the array they're operating on.
The sequence is:
variants[]- get all variants array elements->- dereference each variant reference[variantId in $variantIds]- filter the dereferenced variants[0]- take the first match{...}- project the fields you want
This syntax change should work across all API versions from 2021-03-25 onwards. The v1 API was more lenient with syntax, which is why your original query worked there but fails in later versions.
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.