Unlock seamless workflows and faster delivery with our latest releases – get the details

How to Neatly Organize GROQ Queries

2 replies
Last updated: Jul 28, 2021
I have a groq query that works as I need it to but I’m wondering if there is a nicer way to organise it. I have an object to create a group of insights with various options for filtering such as insight type, category etc. Currently I’m using the
select
function to select the appropriate query string but as I extend the options I’m ending up with more and more nested selects. Here is a reduced example;
"insights": select(
    order == "asc" => select(
        defined(insightType) => select(
            filter == "past" => *[_type == ^.insightType && now() > date]|order(date asc),
            filter == "future" => *[_type == ^.insightType && now() < date]|order(date asc),
            !defined(filter) => *[_type == ^.insightType]|order(date asc)
        )
        ...other options
    )
    order == "desc" => select( ...desc options )
)
Does anyone have any suggestions for a neater way of doing this?
Jul 28, 2021, 8:46 AM
I think this is a pretty clean way to build queries, actually, but I can see how it might get unwieldy.
One way you can potentially improve it (for a slight performance hit, potentially) is to move more stuff into the inner queries. For example, the above could be written:


"insights": select(
    order == "asc" => select(
        defined(insightType) => *[_type == ^.insightType &&
          select(
            filter == "past" => now() > date,
            filter == "future" => now() < date,
            true
          )
        ] | order(date)
        ...other options
    )
    order == "desc" => ...
)
Unfortunately, the same trick cannot be used to refactor
order()
, because it does not accept arbitrary expressions (yet). But you could use JavaScript fragments for that, e.g.:

"insights": select(
    select(
      defined(insightType) => *[_type == ^.insightType &&
        select(
          filter == "past" => now() > date,
          filter == "future" => now() < date,
          true
        )
      ] | order(date ${direction})
    )
)
Here,
${direction}
must be either
asc
 or
desc
.
Jul 28, 2021, 8:56 AM
Cool, thanks for the suggestions.
Jul 28, 2021, 9:01 AM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?