Functions in GROQ defined

Written by Lo Etheridge, Kapehe

In Kap & Lauren learn GROQ - Part 7, we entered the world of GROQ functions and contemplated traveling to the sun or the moon. Kap and I were split on this question, I would much rather go to the moon so that I could have special moon boots! But Kap would travel to the sun and play soccer (fútbol).

GROQ Functions

In GROQ, there are numerous functions you can choose when writing out your queries. Whether you want to find the length of a string or even round up a number to a whole number, functions in GROQ can help you out. To find the full list, visit this function reference page.

In this stream, we covered a handful of them. Let's check them out.

Defined Function

The defined() function takes any argument and evaluates whether it's true, false, or NULL:

*[defined(defaultProductVariant.price)]{
 title, 
 defaultProductVariant{price}
}

Kap and I used the defined() in the above query to filter all of our content that has a price and return the title and price in our projection. This is a departure from the queries we did in previous streams because we are using the defined() to search across all of our documents instead of filtering by a document _type to narrow the scope of our query.

Round Function

The round() function will take any number and round it to the nearest integer or decimal place specified in the function:

*[defined(defaultProductVariant.price)]{
 title, 
 “roundTheNumber”: round(defaultProductVariant.price)
}

Our second query uses round() to round all of the product prices to a whole integer. For example, the round() would return a price of 10 for a candy priced at 9.99.

PortableText [components.type] is missing "example"

In the example above, we took the rounded price and added 3.00 (+ 3) to all prices at once. This would be a great time-saver if you needed to update all of the prices in your store!

Text Function

The text() function is used to return the string or plain text from fields that are portable text blocks or an array of blocks. This function is specific to the pt namespace and only works with portable text.

PortableText [components.type] is missing "gotcha"

A quick note on namespaces:

The Sanity Content Lake has built-in namespaces such as global, pt, geo. If a GROQ function is global, the entire Content Lake is its scope. Whereas, pt and geo functions only pertain to portable text and geolocation namespaces respectively.

Back to our scheduled programming, the text ()...

*[_type == “product”]{
 “plaintextBody”: pt::text(body.en)
}

In this query, we filter on the product document type and return all of the body text within the portable text block for all products. This would be super useful if you needed to edit a bunch of product descriptions or any text.

Length vs Count Functions

Kap & I took the text() query a step further and used the length() to get a character count for each product body text and the count() to get the number of images associated with each product :

*[_type == “product”]{
  “plaintextBody”: length(pt::text(body.en)),
  “imageCount”: count(defaultProductVariant.images),
	title
}

The difference between length() and count() can be confusing at first. The length() will give you the size of an array or the number of characters in a string. But the count() only gives the number of elements that have been passed in an array and is perfect for counting something like how many images are attached to each product.

If you missed the stream, you can watch Kap & Lauren learn GROQ - Part 7 on YouTube. Follow us on Twitch and tune in for another episode of Kap & Lauren learn GROQ, we hope to see you there!