Troubleshooting GROQ query for accessing objects in an array from a Sanity schema
Looking at your query structure, I can see the issue - your projection is creating an array of objects with conditional keys, which makes accessing the data awkward. The good news is there are better ways to handle this in GROQ!
The Problem
Your current query structure creates nested objects within an array:
descriptions[]{
_type == 'descriptionShortProduct' => { "shortDesc": description},
_type == 'descriptionShopify' => { "shopifyDesc": description }
}This gives you an array where each element is either {shopifyDesc: [...]} or {shortDesc: [...]}, making it hard to access the data you want.
Solution 1: Use coalesce() (Recommended)
The cleanest approach is to use GROQ's coalesce() function, which returns the first non-null value from its arguments:
const queryString = `*[_id in ['${referenceArray.join("','")}']]{
...,
"description": coalesce(
descriptions[_type == 'descriptionShortProduct'][0].description,
descriptions[_type == 'descriptionShopify'][0].description
),
"productImage": images[0]-> {...}
}`;This gives you a single description field that automatically falls back from short description to Shopify description.
Solution 2: Filter the Array First
If you need access to both descriptions separately, filter the array to find specific types:
const queryString = `*[_id in ['${referenceArray.join("','")}']]{
...,
"shortDesc": descriptions[_type == 'descriptionShortProduct'][0].description,
"shopifyDesc": descriptions[_type == 'descriptionShopify'][0].description,
"productImage": images[0]-> {...}
}`;Then in your code:
const description = product.shortDesc || product.shopifyDesc;Solution 3: Use select() for More Complex Logic
For more complex conditional logic, you can use select():
const queryString = `*[_id in ['${referenceArray.join("','")}']]{
...,
"description": select(
count(descriptions[_type == 'descriptionShortProduct']) > 0 => descriptions[_type == 'descriptionShortProduct'][0].description,
descriptions[_type == 'descriptionShopify'][0].description
),
"productImage": images[0]-> {...}
}`;The coalesce() approach is usually the cleanest since it automatically handles null/undefined values and gives you exactly what you need - one description field with a fallback chain. This is much easier to work with than trying to navigate the nested array structure your current query produces!
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.