Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

What’s the best way to construct GROQ query dynamically in JavaScript? Is there a sort of way to construct it in objects or any config which will then get translated to a...

5 replies
Last updated: Jan 7, 2021
What’s the best way to construct GROQ query dynamically in JavaScript? Is there a sort of way to construct it in objects or any config which will then get translated to a string query we can use?
I’m unsure whether what I’m doing right now is how it should be. As an example, I defined variables for like:


const baseQuery = (filters) => `*[ ${filters} ]`
const filters = `_type == "products" and name match ${nameKeyword}`
const query = `baseQuery(filters)`
This can go out of hand if I add in projections, additional filters, etc.
Jan 6, 2021, 11:38 AM
I've seen two projects that tries to make an abstraction over GROQ:
https://www.npmjs.com/package/sanity-typed-queries
https://www.npmjs.com/package/sanity-query-helper Maybe you can take some inspiration from there?

But generally, I prefer to just write out every query, makes it a bit easier to debug and for other people to onboard to the project
Jan 6, 2021, 12:59 PM
I've seen two projects that tries to make an abstraction over GROQ:
https://www.npmjs.com/package/sanity-typed-queries
https://www.npmjs.com/package/sanity-query-helper Maybe you can take some inspiration from there?

But generally, I prefer to just write out every query, makes it a bit easier to debug and for other people to onboard to the project
Jan 6, 2021, 12:59 PM
Thanks
user Y
. 👀
Jan 6, 2021, 2:40 PM
The reason why I needed to construct GROQ dynamically is we are sort of creating a product configurator and we do filtering based on user selected option. I guess this wouldn’t be so hard if the data is simple. But since it’s not, we gotta push through. Hmm. Or maybe there’s another approach we could take?
Here’s a simple GROQ based on two filters. It could get more complicated as soon as more options are selected:


*[
   (_type == "product" && defined(productConfigurator[])) 
   && productConfigurator[].itemNumber match '-UWW-'
 ] {
   _id,
   _type,
   title,
   productConfigurator[itemNumber match '-UWW-'] {
     ...,
     tapeLightType->{title}
   }
 } |  [ productConfigurator[tapeLightType.title == "Reel"] ] {
   ...,
   productConfigurator[tapeLightType.title == "Reel"]
 }
Jan 7, 2021, 2:23 AM
Then we try to do it this way before that query turned out above:

const query = `*[
        ${baseFilter}
        ${additionalFilter}
      ] {
        ${baseProjection}
        ${additionalProjections}
      }
      `;
Jan 7, 2021, 2:25 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?