GROQ: Filter product attributes by category's attribute references
Great question! You're looking to filter an array of references based on whether those references match certain criteria. The key is using the @ operator to reference the current element within an array filter.
Here's the solution for your use case:
*[_type == "product"] {
"attrs": attributes[@._ref in ^.category->attributeRefs[]._ref]
}However, if you want to filter based on the actual attribute values (not just the references), you'll want to use this pattern:
*[_type == "product"] {
"attrs": attributes[(@->._id in ^.category->attributeRefs[]._ref)]->
}The most robust solution based on this answer from the Sanity community would be:
*[_type == "product"] {
"attrs": attributes[(@._ref in ^.category->attributeRefs[]._ref)]->,
// ... other fields
}Key concepts here:
@refers to the current element being filtered in the array^allows you to reference the parent scope (the product document)->dereferences the reference to get the full document- The
inoperator checks if a value exists in an array
If you want to go a step further and ensure you only get products that have at least one matching attribute, you can add a filter at the document level:
*[_type == "product"] {
"attrs": attributes[(@._ref in ^.category->attributeRefs[]._ref)]->,
_id
}[length(attrs) > 0]Note: This pattern requires API version v2021-03-25 or later to work properly with the @ operator in array filters.
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.