
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeI can see you're struggling with filtering deeply nested arrays in GROQ. This is a common challenge, and the key is understanding how GROQ handles array traversal in filter conditions versus projections.
The issue you're encountering is that when you write something like:
brodtekst[_type == 'hjelpeartikkel.expandCollapse'].innhold[_type == 'bilde'].marks[]This creates a flattened array of all marks from all matching bilde objects across all matching brodtekst items. When you then check != null, you're not checking whether specific documents have marks, but rather whether this flattened array contains anything.
Here's a working approach using nested count() functions to check for the existence of marks at the right nesting level:
*[_type == 'hjelpeartikkel' &&
count(brodtekst[
_type == 'hjelpeartikkel.expandCollapse' &&
count(innhold[_type == 'bilde' && defined(marks)]) > 0
]) > 0
]{
_id,
"problematicBlocks": brodtekst[_type == 'hjelpeartikkel.expandCollapse']{
innhold[_type == 'bilde' && defined(marks)]{
_key,
_type,
marks
}
}
}This query works by:
count() at each nesting level to properly evaluate whether matching items existinnhold[_type == 'bilde' && defined(marks)] only matches bilde objects that have a marks fieldcount(...) > 0 checks if there's at least one matching expandCollapse itemIf you want to be more specific and only find bilde objects where marks is an array with actual content (not just defined but empty), you can use:
*[_type == 'hjelpeartikkel' &&
count(brodtekst[
_type == 'hjelpeartikkel.expandCollapse' &&
count(innhold[_type == 'bilde' && count(marks) > 0]) > 0
]) > 0
]The count(marks) > 0 ensures you're only matching bilde objects where the marks array actually contains elements.
Why your original attempts didn't work:
brodtekst[].innhold[].marks[] != null flattens all marks across all documents into a single array, then compares that array to null (which will always be true if any marks exist anywhere)array[].nestedArray[] works for projections, when you're using it in filter conditions with comparisons, the flattening behavior can produce unexpected resultscount() at each nesting level gives you explicit control over what you're checking at each depthIf you're still getting unexpected results, you might also try using length(marks) > 0 as an alternative to count(marks) > 0, though they should behave similarly for arrays. Another option is to add && length(marks) > 0 for extra certainty that it's a non-empty array.
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store