GROQ: Query products through shopifyProduct variants to find references

9 replies
Last updated: Jul 15, 2022
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
*[_type == 'product' && _id == 'shopifyProduct-7429472551073']{
  _id,
  "title": shop.title,
  "attributes": *[_type == 'attribute_color'],
  "attributes_real": attributes
}
returns
"result":[1 item
0:{4 items
"_id":"shopifyProduct-7429472551073"
"attributes":[2 items
0:{8 items
"_createdAt":"2022-07-11T15:15:33Z"
"_id":"44feb843-664a-4800-847a-f48ff1deee15"
"_rev":"gw7R8VGfQihCUGoM3ImJHF"
"_type":"attribute_color"
"_updatedAt":"2022-07-13T20:32:37Z"
"key":"apparel_color"
"name":"Apparel Color"
"tag":"apparel"
}
1:{7 items
"_createdAt":"2022-07-08T13:48:12Z"
"_id":"8319f6ae-7fbb-4a96-b6a6-08fc0863ed4e"
"_rev":"o1F9UMohcy1KTaXxhtJRJQ"
"_type":"attribute_color"
"_updatedAt":"2022-07-08T13:48:12Z"
"key":"lure_color"
"name":"Lure Color"
}
]
"attributes_real":[1 item
0:{3 items
"_key":"c827a7fbbd22"
"_type":"attributedvalue_color"
"attribute":{2 items
"_ref":"44feb843-664a-4800-847a-f48ff1deee15"
"_type":"reference"
}
}
]
"title":NULL
}
]
but I'm getting all
attribute_color
in attributes. I just want the
apparel_color
here. Ultimately I want to remove the top level id filter and get all the documents that have a variant that reference
apparel_color
attribute. Or generally any other attribute we've defined.
Hi Phil! 👋 I’m hoping you can help me clarify if this is the core of your question: “I want to … find all `product`s that have a variant that reference a particular document of that type.”
Hi Geoff. I'm starting from this example in the GROQ cheat sheet
// Movies which reference ancient people
*[_type=="movie" && references(*[_type=="person" && age > 99]._id)]{title}
However my
movie (product) does not reference a person (attribute) directly. I'm my schema, product owns an object shopifyProduct that has an array of references to productVariant which has an array of references to attribute. I want to find all the product documents that, thru this round about model, ultimately have a productVariant which has a reference to a particular attribute in its array of attribute references.
Great, thank you. When you say “_product_ owns an object shopifyProduct,” can I confirm that means
shopifyProduct
is an object in the schema (it’s just not showing because it wasn’t included in the projection)?
yes, its defined as an object in the schema. Full disclosure, we started from your reference schema for the Sanity connect app w/ Shopify. Then added a new document type, attribute. The productVariant document has an array of references to type of attribute.
Perfect, thank you. I’m not sure if this’ll work first try, as there are places where we might have structured things differently, but if you want to get a
product
with an array of references that has an array of references containing a title of ‘Apparel Color’, it might look something like this (bear in mind that arrays need names too, so I used
myArray
):

*[_type == 'product' && 'Apparel Color' in shopifyProduct.myArray[]->myArray[]->title]
🔥 🙏 I didn't think to kind of invert the lookup. Many thanks. This was the working query BTW:
*[_type == 'product' && 'apparel_color' in store.variants[]->attributes[].attribute->key]
Excellent! Glad you got it working!

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?