Querying nested array fields with match operator in Sanity
The issue with your GROQ query is in how you're filtering on a nested array field. When you write *[variants[].sku match "*test*"], GROQ interprets this in a way that doesn't work as expected for filtering documents.
The problem is that variants[].sku creates a projection that extracts all SKU values from the variants array, but you can't directly use this projection syntax in a filter condition. Instead, you need to check if any element in the array matches your condition.
Here are the correct ways to query this:
Option 1: Using the in operator (recommended for exact/pattern matches)
*["test1" in variants[].sku]This checks if the string "test1" exists anywhere in the array of SKU values.
Option 2: Using match with a filter on the array
*[count(variants[sku match "*test*"]) > 0]This filters the variants array to only those where sku matches your pattern, counts them, and returns documents where at least one match exists.
Option 3: More explicit version with document type
*[_type == "yourDocumentType" && count(variants[sku match "*test*"]) > 0]Why your original query didn't work:
The syntax variants[].sku is a projection operator that extracts values, not a filter. When you try to use it directly in a filter like *[variants[].sku match "*test*"], GROQ doesn't evaluate it as "any variant's sku that matches", but rather tries to apply the match to the projection result itself, which doesn't work in a filter context.
Best practice:
For substring matching in nested arrays:
*[count(variants[sku match "*test*"]) > 0]For exact matching in nested arrays:
*["test1" in variants[].sku]The key difference is that inside the array filter variants[...], you're working with individual array items, so you directly reference sku without the [] operator. The [] operator is only used when projecting/extracting values, not when filtering within the array itself.
Show original thread6 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.