FormidableLabs / groqd

A schema-unaware, runtime and type-safe query builder for GROQ.
https://commerce.nearform.com/open-source/groqd
MIT License
230 stars 16 forks source link

Subquery within a select #301

Open Designer023 opened 1 week ago

Designer023 commented 1 week ago

Is there an existing issue for this?

Code of Conduct

Question

This is a bit of a strange question, but I have a schema where I have an array of types, so that I can use it as a page builder kind of thing:

{
    name: "content",
    type: "array",
    title: "Content",
    of: [
        defineArrayMember({
            type: "block",
        },
        defineArrayMember({
            type: "image",
        }),
        ...
        // Here's the important one:
        defineArrayMember({
            type: "articleFeed",
        }),
     ]
}

There are more types than in the code, but this is just an example.

I can query each of these in my parent schema using something like:

const query = q("*").filter("page").grab({
  body: q("body[]", { isArray: true }).select({
    "_type == 'image'": ["@", ImageQuery],
    "_type == 'block'": ["@", q.contentBlock()],
    "_type == 'articleFeed'": ["@", q.object({
      // @todo
    })],
  }),
})

I can successfully get the articleFeed data back here, but what I would like to do is to, instead of @ do a "sub query" for a feed of articles. I have managed to do this by replacing the @ with a raw query, but is there any way I can make this into a groqd query, so that it's cleaner and more robust?

.select({
    "_type == 'articleFeed'": ["{items, 'articles': *[_type == 'article']{title, 'slug':slug.current}[1..5] }", ArticleCardQuery],
    })
})

Bonus

Is it conceivably possible to use a value from the articleFeed, such as count or tag so that the article feed can be configured from the sanity CMS?

I'm not worried about if the query is slow as this is a build-time query and won't be run very often

Designer023 commented 1 week ago

Looks like I have figured this out:

Create a query first

const articleFeed =  q("").grab({
  articles: q("*")
    .filterByType("article")
    .grab({
      title: q.string()
    })
})

Then we can use it, and as a bonus we can use the schema too:

{
  "_type == 'articleFeed'":
  [
    articleFeed.query,
    articleFeed.schema
  ]
}