Introducing GROQ-powered Webhooks

Operators

A description of operators in GROQ

Logical Operators

GROQ supports the use of the following logical operators:

  • AND (&&)
  • OR (||)
  • NOT (!=)

The operand – the values the operator evaluates – must be booleans or null. If the evaluation yields an invalid type, it will be coerced to null.

&& – Logical AND

&& returns true if both operands are true; otherwise, it returns false or null.

Truth table

true && true   // returns true

true && false  // returns false

false && true  // returns false

false && false // returns false

true && null   // returns null

false && null  // returns false

null && true   // returns null

null && false  // returns false

null && null   // returns null

GROQ examples

// Checks if a document is: 
// of _type "author"
// AND has a name value of "John Doe"
// If both are true, returns all documents matching
*[_type=="author" && name=="John Doe"]


// Checks if a document is:
// of _type "movie"
// AND has a title of "Arrival"
// If both are true, returns all documents matching
*[_type=='movie' && title == 'Arrival']

// Checks if a document is:
// of _type "movie"
// AND includes the string 'sci-fi' in its genres field
*[_type == 'movie' && 'sci-fi' in genres]

|| Logical OR

|| returns true if either operand is true; otherwise, it returns false or null.

Truth Table

true || true   // Returns true

true || false  // Returns true

false || true  // Returns true

false || false // Returns false

// Null cases

true || null   // Returns true

false || null  // Returns null

null || true   // Returns true

null || false  // Returns null

null || null   // Returns null

GROQ example

// Checks if a document is
// of popularity greater than 15
// OR has a releaseDate after 2016-04-25
// Returns all documents that match EITHER condition
*[popularity > 15 || releaseDate > "2016-04-25"]

! Logical Not

! returns the logical negation of the value of the operand.

Truth table

!true  // Returns false

!false // Returns true

!null  // Returns null

GROQ examples

// Returns all docs that don't start with `drafts.`
*[!(_id in path("drafts.**"))]

// Returns all documents that the boolean `awardWinner` is false
*[!awardWinner]

Comparison Operators

Comparison operators compare two values, returning true if the comparison holds or false otherwise. The operands must be of the same type (except for integers and floats, which are interchangeable). If the operands are of different types, the comparison returns null. If any operand is null, the comparison returns null.

Comparisons are only supported for data types booleans, integers, floats, and strings.

Equality comparisons (== and !=) have the following semantics:

  • Booleans: identical logical truth values.
  • Integers and floats: identical real number values.
  • Strings: identical lengths and Unicode code points (case sensitive).
  • Nulls: always yield null.

Ordered comparisons (>, <, >=, and <=) use the following order:

  • Booleans: true is greater than false.
  • Integers and floats: numerical order.
  • Strings: numerical Unicode code point order (i.e., case-sensitive), compared character-by-character. For overlapping strings, shorter strings are ordered before longer strings.
  • Nulls: always yield null.

== Equality

Returns true if the operands are considered equal.

!= Inequality

Returns true if the operands are considered not equal.

> Greater Than

Returns true if the left-hand operand is greater than (ordered after) the right-hand operand.

< Lesser Than

Returns true if the left-hand operand is lesser than (ordered before) the right-hand operand.

>= Greater Than or Equal

Returns true if the left-hand operand is considered greater than or equal to the right-hand operand.

<= Lesser Than or Equal

Returns true if the left-hand operand is considered lesser than or equal to the right-hand operand.

in Compound Type Membership

// Returns true if document's _type
// is included in the array (either "movie" or "person")
*[_type in ["movie", "person"]]

// Returns true if "myTag" is in tags array
*["myTag" in tags]

Returns true if the left-hand operand is contained within the right-hand operand. The right-hand operand may be an array, range, or path.

If the right-hand operand is an array, the left-hand operand may be of any type. The left-hand operand is compared for equality (==) with each element of the array, returning true as soon as a match is found. If no match is found, it returns null if the array contains a null value, otherwise false.

If the right-hand operand is a range, the left-hand operand must be of the same type as the range endpoints. Returns true if the left-hand operand is ordered between the range endpoints, otherwise false.

If the right-hand operand is a path, the left-hand operand must be a string or path. Returns true if the left-hand operand is matched by the right-hand path pattern, otherwise false.

Access Operators

Because of the nested nature of data, it's often important to access members of compound data types like objects and arrays. Access operators allow the use of nested content in operations.

Access operators will return null if the member does not exist or the operator is incompatible with the left-hand operand's type. Access operators can be chained. Each operator accesses the result of the preceding chain, e.g., object.ref->array[1].

* Everything

Takes no operands and returns an array of all stored documents that the current user has access to. It is typically used at the beginning of a GROQ query pipeline, such as *[ _type == "movie" ]{ title, releaseYear }.

// Returns all items in the root array
*[]

// Returns all items from the root array
// matching the filter provided (documents with _type of "movie)
*[_type == "movie"]

Gotcha

Not to be confused with the * multiplication operator, which takes two operands (the factors to be multiplied).

@ This

Takes no operands, and returns the root value of the current scope, or null if no root value exists.

For example, in the document filter *[ @.attribute == "value" ] it refers to the currently filtered document, and in the expression numbers[@ >= 10] it refers to the currently filtered number of the numbers array.

// @ refers to the root value (document) of the scope
*[ @["1"] ] 

// @ refers to the myArray array
// Returns the total number of items in my Array
*{"arraySizes": myArray[]{"size": count(@)}} 

^ Parent

Takes no operands and returns the root value of the parent scope, or null if no parent scope exists.

// Value of ^ is the current doc in the "someParent" array
*[_type == "someParent"]{ 
  "referencedBy": *[ references(^._id) ]
}

// Using the ^ operator to refer to the enclosing document. Here ^._id refers to the id
// of the enclosing person record.
*[_type=="person"]{
  name,
  "relatedMovies": *[_type=='movie' && references(^._id)]{ title }
}

// person.someObj.parentName returns root name value
*[_type=="person"]{
  name,
  someObj{
    name,
    "parentName": ^.name
  }
}

.<identifier> Object Attribute Access

Returns the value of the object attribute given by the right-hand identifier, e.g. object.attribute.

// Returns the name string from someObject
*[_type == "document"] {
  "nestedName": someObject.name
}

[<string>] Object Attribute Access

Returns the object attribute with the given key, e.g., object["attribute"]. This is equivalent to the . access operator, but useful when the attribute name is not a legal GROQ identifier.

// Returns the illegalIdentifier value from someObject
*[_type == "document"] {
  "nestedName": someObject["illegalIdentifier"]
}

Gotcha

The attribute name must be a string literal due to parser ambiguity with filters.

-> Reference Access (dereference)

Returns the document referenced by the left-hand reference instead of the reference values. It may optionally be followed by an attribute identifier or data projection, in which case it returns the value of the given attribute(s) of the referenced document. If the reference points to a non-existent document (for a weak reference), it returns null.

*[_id == "someDocument"]{
  referencedDoc->, // Returns all data
  "referenceName": referencedDoc->name // Returns the name value
  "referenceProjection" referenceDoc->{
    title,
    description
  } // Returns the title and description
}

[<integer>] Array Element Access

Returns the array element at the given zero-based index, e.g., array[2] yields the third array element. Negative indices are based at the end of the array, e.g., array[-2] yields the second-to-last element.

Protip

This operator is actually the subscript pipeline component in disguise since it has an implicit | operator before it.

Gotcha

The element index must be an integer literal due to parser ambiguity with filters.

[<range>] Array Slice

Returns a new array containing the elements whose indices fall within the range, e.g., array[2..4] yields the new array [array[2], array[3], array[4]]. Ranges may extend beyond array bounds.

Negative range endpoints are based at the end of the array, e.g., array[2..-1] yields all elements from the third to the last. If the right endpoint falls before the left endpoint the result is an empty array.

Gotcha

The range must be a range literal due to parser ambiguity with filters.

[<boolean>] Array Filter

Returns a new array with the elements for which the filter expression evaluates to true, e.g., people[birthYear >= 1980]. The filter is evaluated in the scope of each array element.

Protip

This operator is actually the filter pipeline component in disguise, since it has an implicit | operator before it.

[] Array Traversal

Traverses the left-hand array, applying the optional right-hand access operator to each element and collecting the resulting values in a flat array - e.g., array[].attribute yields a flat array of the attribute attribute value of each array element, and array[]->name yields a flat array of the name attribute values of each document referenced by array. If no right-hand access operator is given, it defaults to returning a flat array containing each traversed element.

// "cast" loops through the castMembers array
// each person dereferences to return each person's name
*[_type=='movie']{title,'cast': castMembers[].person->name}

// Returns
{
  title: "Interstellar",
  cast: [
    "Matthew McConaugheh",
    "Anne Hathaway",
    "Matt Damon",
    ...
  ]
}

... Array/Object Expansion

Expands the right-hand array or object into the surrounding literal array or object.

// In an array
[ ...[1,2], 3, ...[4,5] ]
// Returns
[1,2,3,4,5]
 
// In an object
{ ...{"a": 1}, "b":2, {"c":3} }
//returns
{ "a": 1, "b": 2, "c":3 }

Arithmetic Operators

Arithmetic operators accept any combination of float and integer operands. If any operand is a float, or if the result has a non-zero fractional part, the result is a float; otherwise, it is an integer.

The + operator is also used to concatenate two strings, arrays, or objects.

Gotcha

Floating-point arithmetic is fundamentally imprecise, so operations on floats may produce results with very small rounding errors, and the results may vary on different CPU architectures. For example, 3.14+1 yields 4.140000000000001. The round() function can be used to round results.

+ Addition and Concatenation

Adds two numbers, e.g., 3+2 yields 5. Also acts as a prefix operator for positive numbers, e.g., +3 yields 3.

Also concatenates two strings, arrays, or objects, e.g., "ab"+"cd" yields "abcd". If two objects have duplicate keys, the key from the right-hand object replaces the key from the left-hand one.

- Subtraction

Subtracts two numbers, e.g., 3-2 yields 1. Also acts as a prefix operator for negative numbers, e.g., -3.

* Multiplication

Multiplies two numbers, e.g., 3*2 yields 6.

/ Division

Divides two numbers, e.g., 3/2 yields 1.5. Division by 0 yields null.

** Exponentiation

Raises the left-hand operand to the power of the right-hand operand, e.g., 2**3 yields 8.

Fractional and negative exponents follow the normal rules of roots and inverse exponentiation, so e.g., the square root of 4 is taken with 4**(1/2) (yielding 2), and the inverse square root of 4 is taken with 4**-(1/2) (yielding 0.5).

% Modulo

Returns the remainder of the division of its operands, e.g.,, 5%2 yields 1. The remainder has the sign of the dividend and a magnitude less than the divisor.

Full-Text Search Operators

Full-text search operators perform searches of text content using inverted search indexes. Content is tokenized as words (i.e. split on whitespace and punctuation), with no stemming or other processing.

match Full-text Search

Searches the left-hand operand for individual words that match the text pattern given in the right-hand operand, returning true if a match is found; otherwise it returns false. If the right-hand operand contains null match will return null.

Patterns are strings that use * as wildcards, and any number of wildcards can be used at any position. For example, foo* matches any word starting with foo, and foo*bar matches any word starting with foo and ending with bar. If the pattern does not contain any wildcards, it must exactly match a whole word in the left-hand operand.

Both the left-hand and right-hand operands can be either strings or arrays of strings. All patterns in the right-hand operand must match anywhere in the left-hand operand, e.g. ["foobar", "baz"] match ["foo*", "*bar"] returns true.

// title contains a word starting with "wo"
*[title match "wo*"] 

// title and body combined contains a word starting with "wo" and the full word "zero"
*[[title, body] match ["wo*", "zero"]] 

Known Issue

match with left-hand arrays currently only work as documented with array traversal expressions, e.g. array[].value match "pattern", and then only in certain cases. If the left-hand operand is an array attribute, e.g. array match "pattern", then it never matches. If the left-hand operand is a literal array, e.g. [a, b] match ["x","y"], then all right-hand patterns must match any single string (instead of anywhere in all strings).

Pipeline Operators

Pipelines are a calling convention where a left-hand array is passed to a right-hand pipeline component. Pipelines are constructed via the | operator, which may be implicit. For more information, see the Pipeline Components section.

| Pipe Operator

Passes the left-hand array to the right-hand pipeline component and returns the result, e.g., * | order(_id).

Operator Precedence

Operator precedence is listed below, in descending order and with associativity in parenthesis:

  • . (left), | (left)
  • -> (left)
  • ** (right)
  • * (left), / (left), % (left)
  • + (left), - (left), ! (right)
  • ... (right)
  • == , !=, >, >=, <, <= (all left), in (left), match (left)
  • && (left)
  • || (left)
  • * (none), @ (none), ^ (none)

Precedence can be overridden by grouping expressions with (), e.g. (1+2)*3.

Was this article helpful?