Content Lake (Datastore)

Custom GROQ functions

Learn how to create your own GROQ functions.

Sometimes you find yourself repeating the same portion of a GROQ query across multiple queries, or even within a single complex query. Custom functions for GROQ allow you to create modular, reusable sub-queries.

Prerequisites:

  • Custom GROQ functions are available on all API versions except v1.

Function anatomy

Custom functions look similar to other GROQ functions, but with some limitations. They include a namespace and accept a parameter. Let's look at an example function that follows a reference and returns a projection that combines an author's first and last name.

fn ex::name($author) = $author-> { "name": firstName + " " + lastName };

*[_type == 'post']{
  "author": ex::name(author)
}

All functions start with the fn keyword and contain a namespace, name, parameter, and function body. In the example above:

  • ex is the namespace.
  • name is the function name.
  • $author is the parameter.
  • $author-> { "name": firstName + " " + lastName } is the body.

Custom function declarations must happen at the start of the GROQ query and each declaration must end with a semicolon (;). You can use them anywhere you'd normally send a GROQ query, such as a Sanity client, the HTTP query API, or the Vision tool. For example, in @sanity/client:

const QUERY = `
fn ex::name($author) = $author-> { "name": firstName + " " + lastName };

*[_type == "post"]{
  "author": ex::name(author)
}`

const posts = await client.fetch(QUERY)

See the GROQ functions reference for additional details.

Examples

Custom functions support a limited set of formats at this time:

  • $param{...}
  • $param->{...}
  • $param[]{...}
  • $param[]->{...}

Let's use the following documents as an example to explore each format. There is a person document, an occupation document, and two pet documents.

Basic projection

First we'll define a function that returns a basic projection. This function, ex:: details, takes a $person parameter and returns a projection containing their name and age. To use the function, we pass in @ to represent the person returned by the filter.

Follow references

It's common to follow references to include part or all of their contents in the referencing object. This function follows the person's occupation reference and returns a projection with their title.

Array projection

This function iterates through the person's belongings to display their names.

Array of references

This function follows each reference in the person's pet key.

Limitations

At this time, functions are limited to the formats displayed above. Additionally, custom functions do not yet support:

  • Recursion.
  • Accessing the parent scope.
  • Passing multiple parameters.
  • Accessing the function parameter more than once in the function body.
  • Calling a custom function from within a custom function.

Was this page helpful?