TracksMastering Content OperationsCoursesBetween GROQ and a hard placeHandling missing values
Between GROQ and a hard place
Markdown Version

Handling missing values

Log in to watch a video walkthrough of this lesson
Log in
Video thumbnail
Named attributes in a projection will return null by default, but they don't have to.
Log in to mark your progress for each Lesson and Task

The following query will only return attributes that exist in the matching document because no attributes have been defined in a projection.

*[_type == "event"][0]

However if you now add a projection and define an attribute which does not exist, instead of being absent from the response, it will return as null.

Query for an attribute that doesn't exist
*[_type == "event"][0]{
fakeAttribute
}

This is null response is expected and in many cases useful—but it can be annoying to handle in your front end.

It's good practice to use projections but now you have to expect every attribute to potentially be null, and this requires a lot of defensive coding.

For example:

data?.headline?.name ?? 'Headliner not yet confirmed'

With a little extra GROQ you can prevent null values and return explicit values instead.

The coalesce() function returns the first value that is not null.

Query for events which may or may not have a headline artist reference and always return a string
*[_type == "event"][0...5]{
"headline": coalesce(headline->name, "Unconfirmed")
}

You can use this same tactic values other than strings, you can do numbers too, or...

Similarly, the coalesce function can be used to always return an array—even an empty array—which can be preferable to null.

The details Portable Text field is an array of block content.

Query for events and always return an array for the Portable Text content
*[_type == "event"][0...5]{
"details": coalesce(details, [])
}

Now instead of checking if details is an array and if it has blocks, you need only check its length.

Setting aside the fact that I think you should avoid using booleans at all—string literals are type safe and more flexible—if you have a boolean field you can make sure it only ever returns a boolean value.

Your current schema does not have a boolean field type. But to always return booleans, create a boolean value in the query.

For example, if you had a boolean field called isSoldOut and queried it like this:

*[_type == "event"]{
isSoldOut
}

The resulting isSoldOut could be one of true, false or null (the last of which is falsy, but still this negates the point of a boolean, right?)

You can always return a boolean by querying for it like this:

*[_type == "event"]{
"isSoldOut": isSoldOut == true
}

Now isSoldOut is only ever true or false.

With all that, you're much sharper on all things GROQ! Good luck completing the rest of the Mastering Content Operations track

You have 3 uncompleted tasks in this lesson
0 of 3