Querying with GROQ in Sanity and optimizing API usage

28 replies
Last updated: Jun 20, 2022
Hey everyone. Would anyone be able to help with me with a question? In GROQ how can I query the results of a query?. I want to avoid having to prefix all my subqueries with ignoring drafts. This is bad code I can tell…
Jun 20, 2022, 8:28 AM
You can chain curly brackets to do that.
*[ ] { 
  /* first pass */
 } {
  /* second pass, using props from 1st */
}
Jun 20, 2022, 8:29 AM
Oh wow, yes that makes sense
Jun 20, 2022, 8:30 AM
If your queries are unrelated and you’re not too tight on API usage, you could also do them separately entirely so they can be parallelized.
Jun 20, 2022, 8:30 AM
Yeah was trying to keep api hits to min. Pretty new to GROQ as you can tell 😆
Jun 20, 2022, 8:31 AM
Makes sense. It’s also fine. Unless your dataset is huge, your queries are most likely not going to be noticeable slow, so parallelization at the cost of API usage might not be worth it.
Jun 20, 2022, 8:32 AM
Awesome, thank you 🙏
Jun 20, 2022, 8:33 AM
I’d need to refer back up to the parent query somehow to get the results though?
Jun 20, 2022, 8:38 AM
Right, you can reference properties you defined in previous projections (brackets).
Jun 20, 2022, 8:40 AM
*[!(_id in path("drafts.**") && defined(slug.current))] {
  ...,
} {
  'topics': @[_type == 'topic'],
}
Jun 20, 2022, 8:41 AM
Something like that?
Jun 20, 2022, 8:41 AM
Mmmh, I‘m not exactly sure. What are you trying to achieve?
Jun 20, 2022, 8:42 AM
I’m just kinda trying to scope some child queries with that first query. So first query gets all documents that are not draft and have a slug. Then second creates a key called topics that has all topic documents (that are not draft and have a slug)
Jun 20, 2022, 8:44 AM
Maybe I am trying to be too clever, and would just be better done with multiple queries?
Jun 20, 2022, 8:45 AM
*[ defined(slug.current) ] {
  "resources": _type == "article-resource" => { ... },
  "stories": _type == "article-story" => { ... },
}
Jun 20, 2022, 8:45 AM
What about something like this?
Jun 20, 2022, 8:45 AM
The result I am looking for is a single object, with arrays of documents for each of those keys. That would return an array no?
Jun 20, 2022, 8:48 AM
Can you please share the code of your initial query? So I can play with it in a text editor without having to retype it all.
Jun 20, 2022, 8:49 AM
Absolutely, hold on
Jun 20, 2022, 8:49 AM
{
  'topicsToc': *[!(_id in path("drafts.**")) && _id == "topic-toc"][0],
  'topics': *[!(_id in path("drafts.**")) && _type == "topic" && defined(slug.current)] {
  'articles': {
    'resources': *[!(_id in path("drafts.**")) && _type == "article-resource"],
    'stories': *[!(_id in path("drafts.**")) && _type == "article-story"],
    'support': *[!(_id in path("drafts.**")) && _type == "article-support"],
    'general': *[!(_id in path("drafts.**")) && _type == "article-general"],
    'technique': *[!(_id in path("drafts.**")) && _type == "article-technique"],
  }
}
Jun 20, 2022, 8:50 AM
Really appreciate it. Been working with SQL for 20 years and feeling like a newbie web dev all over again 😆
Jun 20, 2022, 8:51 AM
Alright, so I looked at the query a bit more, and I think it’s good actually. You can’t really optimize it further, because you always query different collections. You could only tighten it if your queries would be related to one another.
Jun 20, 2022, 8:52 AM
Oh cool, ok great
Jun 20, 2022, 8:54 AM
I’ll proceed with that then, thanks!
Jun 20, 2022, 8:55 AM
There’s no way of creating a re-usable bit of query code in raw GROQ is there? To avoid the repetition.
Jun 20, 2022, 8:57 AM
Could do in the template literal I guess…
Jun 20, 2022, 8:58 AM
A query is just a string at the end of the day, so you can compose it the way you want. 🙂
Jun 20, 2022, 8:58 AM
True. It’s a very different mindset than I am used to. Thanks again 🙂
Jun 20, 2022, 8:59 AM
Of course!
Jun 20, 2022, 9:00 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?