GROQ: Query products through shopifyProduct variants to find references

9 replies
Last updated: Jan 28, 2026
Hello 👋 . I'm using the sanity + shopify reference schema from here . At least close enough to it w.r.t. the objects and references for "sanity" products and variants vs. objects for the shopify products and variants. I've added an array of references to
productVariant
that point to some other new document type. I want to use the
references()
function to find all `product`s that have a variant that reference a particular document of that type. I cannot figure out how to drill down in GROQ from a
*[_type == 'product']
thru the
shopifyProduct
object which references a
productVariant
which ultimately has the reference to the document I'm considering. Thanks for any help.
AI Update

When working with nested references in a Shopify + Sanity schema, the key is using GROQ's in operator combined with the reference access operator (->) to traverse through multiple levels of references.

Based on your schema structure where:

  • product documents have a store object (or similar)
  • That object contains a variants array with references to productVariant documents
  • Each productVariant has an array field (like attributes) containing references to your custom attribute documents

The solution is to use the in operator to check if a specific value exists anywhere in the dereferenced chain:

*[_type == 'product' && 'your-attribute-id' in store.variants[]->attributes[]->_id]

Or if you're looking for a specific field value within the attribute:

*[_type == 'product' && 'apparel_color' in store.variants[]->attributes[].attribute->key]

How this works:

  1. store.variants[]-> dereferences all variant references in the array
  2. attributes[] accesses the attributes array in each dereferenced variant
  3. .attribute-> (if attributes contain references) or just -> dereferences each attribute reference
  4. Finally, access the field you want to match against (like key, _id, etc.)
  5. The in operator checks if your target value exists anywhere in the resulting flattened array

GROQ automatically flattens nested arrays when you chain array accessors ([]), which makes this pattern work elegantly for deeply nested references.

You can learn more about the references() function and the reference access operator (->) in the GROQ documentation. While references() is great for direct references, the in operator with dereferencing is more flexible for these nested relationship queries.

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