GROQ: Prevent null values when resolving optional array keys

21 replies
Last updated: Nov 14, 2022
In GROQ, when resolving arrays, how do I only get the key if it exists, to prevent companies:null on array items where the key
companies
doesn’t exist?
{ ..., content[]{ ..., companies[]{ ..., company-> } }
I tried
defined()
but I can’t seem to figure out the correct usage, or maybe that doesn’t even work here?
AI Update

Perfect! You're on the right track with defined(). The solution is to use conditional projection to only include the companies key when it exists. Here's how to do it:

{
  ...,
  content[]{
    ...,
    defined(companies) => {
      "companies": companies[]{
        ...,
        company->
      }
    }
  }
}

The key is wrapping the field in a conditional projection using the => operator. When companies is defined, it includes the companies key with its resolved array. When it's not defined, the entire key is omitted from the result (rather than appearing as companies: null).

As mentioned in the defined() function documentation, when using the API, you need to wrap the return value in curly braces with the key name explicitly stated as a string.

If you have multiple conditional fields at the same level, you can chain them:

{
  ...,
  content[]{
    ...,
    defined(companies) => {
      "companies": companies[]{..., company->}
    },
    defined(otherField) => {otherField}
  }
}

This pattern works because defined() returns true when the property exists and is not null, and the conditional projection operator => only includes the result when the condition is true.

Show original thread
21 replies
Have you tried to filter it? Maybe something like
{ ..., content[defined(companies)]{ ..., companies[]{ ..., company-> } }

I want all items in
content
.Some items have
companies
key, with companies in. But some doesn’t.
I don’t want those that haven’t got companies to have
companies:null
.
so you basically just want the key removed?
in those cases
The key should only be there if it is defined.
maybe you could do a select then,
{ ..., content[] { ..., companies[] { ..., ...select( defined(company) => { "company": company-> })
Wouldn’t that still result in
companies:null
?
yea you should move the select to companies instead of company, i just read it wrong
Ah great.. Thank you very much Casper. 💪
btw not sure about performance etc, maybe it is a heavier query to do, usually groq questions are resolved quite quickly in groq
It doesn’t matter in my case, as I am just building a static website from it on build time.I actually posted a question in
groq first, but ther were no reply so I deleted it and posted it in help. 😄
are you building in js? curious why you need the null values removed, since undefined vs null can be handled nearly the same. complexity of the query increases a bit
Yea it’s just my OCD that don’t want keys that aren’t supposed to be there… 🙈
And want to learn GROQ in detail, so I just thought about how that would be possible, and couldn’t get it to work.
could be a more elegant way than select though... reading through the docs you can probably do an inline condition:
{ ..., content[] {
  ...,
  defined(companies) => { /* and so on */ }
}
I never saw
=>
for projection, only
->
.So that’s because it’s a different set? That means I could have another query if it was not defined, right?
=> is a conditional
Ah okay, so because defined returns a boolean, then the following projection is executed?
yea, basically what
...select()
does but a bit easier
Great. Thanks a lot Casper. 💪

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?