How to filter out null responses in GROQ query when collecting tags?

24 replies
Last updated: Mar 6, 2023
Hello! I am wondering how I can filter out all
null
responses in this GROQ query…My goal is to basically sift thru my entire response and get all the “tags” from blog, image, and imageCollections.

*[_type == "blogPost" && _id =="e79ed544-8747-4114-9461-3935791eb7bc"]{
  "blogTags": tags[]->{"slug": slug.current, tagName},
    
  "mainImageTags": mainImage->.tags[]->{"slug": slug.current, tagName},
    
  "imageCollectionTags": body[]{
        _type == 'imageCollectionRef' => @->{
          collectionImages[]->{tags[]}
        }
  }.collectionImages[].tags[]->{"slug": slug.current, tagName},
}
AI Update

Great question! Filtering out null values in GROQ can be done using the defined() function. Looking at your query, you're getting nulls because some of those reference chains or array traversals might not exist on every document.

Here are a few approaches to filter out nulls:

Option 1: Use defined() in array filters

You can filter arrays as you traverse them by adding defined() checks:

*[_type == "blogPost" && _id =="e79ed544-8747-4114-9461-3935791eb7bc"]{
  "blogTags": tags[defined(@)]->{"slug": slug.current, tagName},
    
  "mainImageTags": mainImage.tags[defined(@)]->{"slug": slug.current, tagName},
    
  "imageCollectionTags": body[_type == 'imageCollectionRef']@->{
    collectionImages[]->{tags[defined(@)]}
  }.collectionImages[].tags[defined(@)]->{"slug": slug.current, tagName},
}

The @ symbol refers to the current element being evaluated in the array.

Option 2: Flatten and filter at the end

If you want to collect all tags into a single array and filter nulls, you can use array flattening:

*[_type == "blogPost" && _id =="e79ed544-8747-4114-9461-3935791eb7bc"]{
  "allTags": [
    ...tags[]->{"slug": slug.current, tagName},
    ...mainImage.tags[]->{"slug": slug.current, tagName},
    ...body[_type == 'imageCollectionRef']@->.collectionImages[].tags[]->{"slug": slug.current, tagName}
  ][defined(slug)]
}

The ... spread operator flattens arrays, and [defined(slug)] filters out any null entries (since tags without a slug are likely null).

Option 3: Use select() with defined() for conditional inclusion

For more complex conditional logic, you can use the select() function:

*[_type == "blogPost" && _id =="e79ed544-8747-4114-9461-3935791eb7bc"]{
  "blogTags": select(
    defined(tags) => tags[]->{"slug": slug.current, tagName},
    []
  ),
  // ... rest of query
}

The key insight is that defined() returns true if a property exists and is not null, making it perfect for filtering out those unwanted null values. You can apply it at different stages of your query depending on where the nulls are appearing!

Show original thread
24 replies
Here is the response:
IDK about how to do it using GROQ or sanity but if you are using JS or TS, you can check it by applying
if
conditional statements. But there'll be way in sanity and that would be better option then this one.
You can use it for temporary purpose.
Thanks! Yeah you mean
array.filter(item => item !== null)
?
Great! Thanks for sharing your answer with the community sir :saluting_face:
Yeah ideally I can do this with sanity groq query
Or maybe there is a better way to GROQ query for all nested “tags[]” fields?
Hey, Do you have any experience in making an array of images in a document?
user P
Hey here you can see how I created an array of strings, Is it possible with images too?
sorry wrong thread
You can filter the
tags
array inside of GROQ. Ex:
tags[@ != null]
or possibly:

tags[defined(@)]
thank you, so that would go inside of each
tags[]
?
Exactly. I also just remembered that if you’re dealing with an array of strings you can use the
array::compact()
function . I don’t believe it’ll work on an array of objects, though.
ok thanks
So I am still getting `null`…
*[_type == "blogPost" && _id =="e79ed544-8747-4114-9461-3935791eb7bc"]{
  "imageCollectionTags": body[]{
        _type == 'imageCollectionRef' => @ ->,
  }.collectionImages[]->.tags[@ != null]->{"slug": slug.current, tagName},
}
Im wondering if I should try making just an array of strings and trying compact
great that worked! now i will try to filter out the nulls the other way
will try to do it on object array
ooo it did!!
yesss this is gold thank you
mind blown
I love it when GROQ does something you didn’t think it could do.
is there a way to only get unique values and form a a set?
looks like array::unique
love it

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?