Skip to main content

Functions

The GROQ language has many functions.

GroqD supports several of these in a strongly-typed way.

.count(expression)

Calls the count function, to count the number of items in an expression.

It can be called in a projection, like:

const products = q.star.filterByType("product").project(sub => ({
imagesCount: sub.count("images[]")
}))

You can pass a simple projection string like above, or you can pass a more complex query, like:

const products = q.star.filterByType("product").project(sub => ({
imagesCount: sub.count(sub.field("images[]").filterBy("asset != null"))
}))

This can also be called at the root level, like:

const productCountQuery = q.count(q.star.filterByType("product"));

.coalesce(...expressions)

Calls the coalesce function, which returns the first non-null value.

This can be called in a subquery, like:

const productsQuery = q.star.filterByType("product").project(sub => ({
title: sub.coalesce("title", "metadata.title", "category.title", q.value("DEFAULT"))
}))

You can pass any mix of simple projection strings, and complex queries:

const productsQuery = q.star.filterByType("product").project(sub => ({
title: sub.coalesce(
"title",
"metadata.title",
sub.field("categories[]").slice(0).deref().field("title"),
q.value("DEFAULT")
)
}))

This can also be called at the root level, like:

const x = q.coalesce(
q.star.filterByType("product").filterBy("slug.current === $slug").slice(0),
q.star.filterByType("variant").filterBy("slug.current === $slug").slice(0),
q.star.filterByType("category").filterBy("slug.current === $slug").slice(0),
)

.raw(expression, validation?)

The .raw function is an "escape hatch" for any query that's not yet supported by GroqD.

This can be very useful for GROQ functions, like array::compact() or geo::distance().

You must either specify the type via .raw<T>(expression), or provide a type validation parameter via .raw(expression, validation).

q.star.filterByType("storefront").project(sub => ({
distance: sub.raw("geo::distance(geoPoint, $currentLocation)", z.number()),
isInDeliveryZone: sub.raw<boolean>("geo::contains(deliveryZone, $currentLocation)")
}))