Dynamic GROQ Query in JavaScript

As you use Sanity.io’s GROQ more and more, you’ll soon get yourselves into situations where you’ll have to construct your queries dynamically. A very good example of that is say, you’re working on getting all products based on different attributes.

Imagine we have the following product filters below and their options:

Now, the user first then filters the products by selecting a color attribute of value Red .

We could then write our query like this below:

This post is originally posted on my site’s blog at dorelljames.com. Click here if you can’t read the entire article.

But let’s say, now our user also selects a size of value Small, and so now, it looks like this:

And once more, the user selects a gender of value Female, so finally like this. Whoops…

In situations like this, we’ll need to write our GROQ query dynamically that’s because only then we can formulate it when the user has done a selection. What’s more, is that the values Red , Small , and Female are dynamic too. So basically we have two things to do:

  1. Construct our query properly based on selected product filters
  2. Substitute the values in

In JavaScript, we could use template literals to take care of the second task like this below:

But if we use the code above when the user has filtered the products by color only then we’ll get an incorrect GROQ query, sometimes malformed:

Not good! 😔

One last thing before we go all out! The above example is pretty contrived, GROQ queries aren’t just as simple as that. It can get more complicated especially when we’re working with all different shapes of data. In some challenging datasets, there are times that we’ll do one or many forms of projections, joins, filters, orders, pipes, and so many more.

There are tons of possibilities really and as another example, here below we added some projections to pick specific fields we want to get:

We’ll get back to that later. But for now, the real question is:

How can we create a dynamic GROQ query that will be able to handle any complexity and flexible enough?

If you haven’t had the chance to learn GROQ, you might be interested in learning the basics here and/or probably check out why I could think GROQ as a GraphQL alternative here.

For a start, we can use template literals to do some string interpolation.

This will give us exactly what we’re looking for and the value of our query will be:

To take this a step further, instead of writing the filters by ourselves, we can use the Array.reduce function on our object to construct it dynamically.

Awesome. Now we’re unto something…

But can we take this a step further? Remember, GROQ queries can get more complicated.

Back from our previous example:

If we digest this out, we’ll most probably come with this structure:

And so, we could create projections too to take care of that. Nice!

Now, what if we the user has decided to order the results by price? And our query looks like this now below.

Well, we can create order you’d say, just like below:

And so, altogether, it’ll be like this:

Sounds like we’ve made some progress but we can do more. Yes! See below.

A more advanced form of template literals is tagged templates. This allows us to better compose our queries and supply the values later on instead of providing them ahead.

For the sake of example, I created a groq tagged template function but I think you’re probably better of using minify-groq created by Espen Hovlandsdal of Sanity.io’s Principal Engineer. Check it out!

As I explored this area, there are packages you can use to simplify this task for you. Just take note though that it may not cover all use cases you might have. I’ll list them out in the Resources below. I personally just make use template literals or tagged templates and/or a combination of both.

So here you go on how to build a dynamic GROQ query in javascript and some examples.

What do you think? I’d like to hear your opinion.

  • GROQ tagged template literal — Used to signal that it represents a GRQO-query. The result will be the exact same string as the input — this is currently helpful for getting syntax highlighting in editors, but in the future, it might also parse and validate queries, strip unnecessary whitespace, and similar.
  • minify-groq — Minifies a GROQ-query by reducing unnecessary whitespace and supports placeholder(s) just like in my example above. I would personally say that you use this.
  • How Queries Work — GROQ — A tutorial on using the Sanity query language GROQ. This will give you an idea of how GROQ works.
  • sanity-typed-queries — More than just a query builder but also a schema generator that is fully-typed and works in JavaScript and TypeScript.
  • sanity-query-helper — provides an API that might be easier to understand to build queries.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store