Structured Content 2022: Join our conference to explore fresh perspectives on content and digital experiences →

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.io: Get the most out of your content

Sanity.io is a platform to build websites and applications. It comes with great APIs that let you treat content like data. Give your team exactly what they need to edit and publish their content with the customizable Sanity Studio. Get real-time collaboration out of the box. Sanity.io comes with a hosted datastore for JSON documents, query languages like GROQ and GraphQL, CDNs, on-demand asset transformations, presentation agnostic rich text, plugins, and much more.

Don't compromise on developer experience. Join thousands of developers and trusted companies and power your content with Sanity.io. Free to get started, pay-as-you-go on all plans.