Edit

Share via


GQL expressions, predicates, and functions

Note

This feature is currently in public preview. This preview is provided without a service-level agreement, and isn't recommended for production workloads. Certain features might not be supported or might have constrained capabilities. For more information, see Supplemental Terms of Use for Microsoft Azure Previews.

This article provides a comprehensive reference for GQL expressions, predicates, and built-in functions available in Fabric Graph queries. Use this reference to understand how to perform calculations, filter results, and transform data in your graph queries.

For an overview of the GQL query language and end-to-end query examples, see GQL language guide. For information about supported data types and literal syntax, see GQL values and value types.

Literals

Literals are simple expressions that directly evaluate to the stated value. The GQL values and value types article explains literals of each kind of value in detail.

Example:

1
1.0d
TRUE
"Hello, graph!"
[ 1, 2, 3 ]
NULL

For detailed literal syntax for each data type, see GQL values and value types.

Predicates

Predicates are boolean expressions that you commonly use to filter results in GQL queries. They evaluate to TRUE, FALSE, or UNKNOWN (null).

Caution

When you use predicates as a filter, they retain only those items for which the predicate evaluates to TRUE.

Comparison predicates

Use these operators to compare values:

  • = (equal)
  • <> (not equal)
  • < (less than)
  • > (greater than)
  • <= (less than or equal)
  • >= (greater than or equal)

GQL uses three-valued logic where comparisons with null return UNKNOWN:

Expression Result
5 = 5 TRUE
5 = 3 FALSE
5 = NULL UNKNOWN
NULL = NULL UNKNOWN

For specific comparison behavior, see the documentation for each value type in GQL values and value types.

Example:

MATCH (p:Person)
FILTER WHERE p.birthday <= 20050915
RETURN p.firstName

Number coercion rules:

Use the following rules in order of precedence:

  1. Comparison expressions that involve arguments of approximate numeric types coerce all arguments to be of an approximate numeric type.
  2. Comparison expressions that involve arguments of both signed and unsigned integer types coerce all arguments to be of a signed integer type.

Logical expressions

Combine conditions with logical operators:

  • AND (both conditions true)
  • OR (either condition true)
  • NOT (negates condition)

Example:

MATCH (p:Person)
FILTER WHERE p.birthday <= 20050915 AND p.firstName = 'John'
RETURN p.firstName || ' ' || p.lastName AS fullName

Property existence predicates

To check if properties exist, use these predicates:

p.locationIP IS NOT NULL
p.browserUsed IS NULL

Note

Attempting to access a known non-existing property results in a syntax error. Access to a potentially non-existing property evaluates to null. The determination of whether a property is known or potentially non-existing is based on the type of the accessed node or edge.

List membership predicates

Test if values are in lists:

p.firstName IN ['Alice', 'Bob', 'Charlie']
p.gender NOT IN ['male', 'female']

String pattern predicates

Match strings by using pattern matching techniques:

p.firstName CONTAINS 'John'
p.browserUsed STARTS WITH 'Chrome'
p.locationIP ENDS WITH '.1'

Arithmetic expressions

Use standard arithmetic operators with numeric values:

  • + (addition)
  • - (subtraction)
  • * (multiplication)
  • / (division)

Arithmetic operators follow general mathematical conventions.

Precedence:

Generally, operators follow established operator precedence rules, such as * before +. Use parentheses to control evaluation order as needed.

Example:

(p.birthday < 20050915 OR p.birthday > 19651231) AND p.gender = 'male'

Coercion rules:

Use the following rules in order of precedence:

  1. Arithmetic expressions involving arguments of approximate number types return a result of an approximate numeric type.
  2. Arithmetic expressions involving arguments of both signed and unsigned integer types return a result of a signed integer type.

Example:

LET birth_year = p.birthday / 10000
RETURN birth_year

Property access

Access properties by using dot notation:

p.firstName
edge.creationDate

List access

Access list elements by using zero-based indexing:

interests[0]    -- first element
interests[1]    -- second element

Built-in functions

GQL supports various built-in functions for data processing and analysis.

Aggregate functions

Use aggregate functions to evaluate an expression over a set of rows and get a final result value by combining the values computed for each row. Graph supports the following aggregate functions:

  • count(*) - counts rows
  • sum(expression) - sums numeric values
  • avg(expression) - averages numeric values
  • min(expression) - finds minimum value
  • max(expression) - finds maximum value
  • collect_list(expression) - collects values into a list

In general, aggregate functions ignore null values and always return a null value when no material input values are provided. You can use coalesce to get a different default value: coalesce(sum(expr), 0). The only exception is the count aggregate function, which always counts the non-null values provided, returning 0 if there are none. Use count(*) to include null values in the count.

Use aggregate functions in three different ways:

  • To compute (vertical) aggregates over whole tables
  • To compute (vertical) aggregates over subtables determined by a grouping key
  • To compute (horizontal) aggregates over the elements of a group list

Vertical aggregates:

-- Vertical aggregate over whole table
MATCH (p:Person)
RETURN count(*) AS total_people, avg(p.birthday) AS average_birth_year
-- Vertical aggregate with grouping
MATCH (p:Person)-[:isLocatedIn]->(c:City)
RETURN c.name, count(*) AS population, avg(p.birthday) AS average_birth_year
GROUP BY c.name

Horizontal aggregates:

Horizontal aggregation computes aggregates over the elements of group list variables from variable-length patterns:

-- Horizontal aggregate over a group list variable
MATCH (p:Person)-[edges:knows]->{1,3}(:Person)
RETURN p.firstName, avg(edges.creationDate) AS avg_connection_date

Horizontal aggregation always takes precedence over vertical aggregation. To convert a group list into a regular list, use collect_list(edges).

Note

For comprehensive coverage of aggregation techniques including variable-length edge binding and combining horizontal/vertical aggregation, see Advanced Aggregation Techniques.

String functions

  • char_length(string) - returns string length.
  • upper(string)- returns uppercase variant of provided string (US ASCII only).
  • lower(string)- returns lowercase variant of provided string (US ASCII only).
  • trim(string) - removes leading and trailing whitespace.
  • string_join(list, separator) - joins list elements with separator.

Example:

MATCH (p:Person)
WHERE char_length(p.firstName) > 5
RETURN upper(p.firstName) AS name_upper

Graph functions

  • nodes(path) - returns nodes from a path value.
  • edges(path) - returns edges from a path value.
  • labels(node_or_edge) - returns the labels of a node or edge as a list of strings.

Example:

MATCH p=(:Company)<-[:workAt]-(:Person)-[:knows]-{1,3}(:Person)-[:workAt]->(:Company)
RETURN nodes(p) AS chain_of_colleagues

List functions

  • size(list) - returns size of a list value.
  • trim(list,n) - trim a list to be at most of size n.

Example:

MATCH (p:Person)-[:hasInterest]->(t:Tag)
WHERE size(collect_list(t)) > 3
RETURN p.firstName, collect_list(t.name) AS interests

Temporal functions

  • zoned_datetime() - returns the current zoned datetime.
  • zoned_datetime("2025-09-12T10:10:52Z") - returns the zoned datetime given by the argument in ISO 8601 format.

Example:

RETURN zoned_datetime() AS now

Generic functions

  • coalesce(value1, value2, ...) - returns the first non-null value.

Example:

MATCH (p:Person)
RETURN coalesce(p.firstName, 'Unknown') AS display_name