Switch services using the Version drop-down list. Learn more about navigation.
Applies to: ✅ Azure Data Explorer
This article lists the scalar functions, operators, and predicates supported in GQL (Graph Query Language).
The examples use the movies graph G() from Create a graph and set a graph reference: Person nodes (Name, Born), Movie nodes (Title, Description, Year), and ACTED_IN / DIRECTED edges (Role).
Access operators
Use these operators to read a property or element from a node, edge, map, list, or path.
| Operator |
Description |
x.property |
Access a property of a node, edge, or map by name. |
x[i] |
Access a list or path element by zero-based position, or a map member by key. |
match () limit 1 return [10, 20, 30][1] as byIndex, {a: 1, b: 2}.a as byDot, {a: 1, b: 2}['b'] as byKey
| byIndex |
byDot |
byKey |
| 20 |
1 |
2 |
String functions
| Function |
Description |
LEFT(s, n) |
First n characters of s. |
RIGHT(s, n) |
Last n characters of s. |
UPPER(s) |
Convert s to uppercase. |
LOWER(s) |
Convert s to lowercase. |
TRIM(s), BTRIM(s) |
Remove spaces from both ends of s. BTRIM is a synonym of TRIM(s). |
LTRIM(s) |
Remove spaces from the start (left) of s. |
RTRIM(s) |
Remove spaces from the end (right) of s. |
TRIM([BOTH \| LEADING \| TRAILING] [chars] FROM s) |
Remove chars (or spaces when chars is omitted) from the chosen end of s. The default is BOTH. |
CHAR_LENGTH(s), CHARACTER_LENGTH(s) |
Number of characters in s. |
STRING_JOIN(list, separator) |
Concatenate list items into a string. |
s1 \|\| s2 |
Concatenate strings s1 and s2. |
String predicates:
| Predicate |
Description |
s STARTS WITH prefix |
true when s begins with prefix. Add NOT to negate: s NOT STARTS WITH prefix. |
s ENDS WITH suffix |
true when s ends with suffix. Add NOT to negate: s NOT ENDS WITH suffix. |
s CONTAINS substring |
true when substring occurs anywhere in s. Add NOT to negate: s NOT CONTAINS substring. |
match () limit 1 return upper("abc") as result
match () limit 1 return trim(leading 'a' from 'aabc') as result
match () limit 1 return string_join(["a", "bc"], "") as result
MATCH (p :Person)
WHERE p.Name starts with 'T'
RETURN p.Name as actorName
Numeric functions
| Function |
Description |
ABS(x) |
Absolute value of x. |
SQRT(x) |
Square root. |
EXP(x) |
e raised to x. |
LN(x) |
Natural logarithm. |
LOG10(x) |
Base-10 logarithm. |
FLOOR(x) |
Largest integer ≤ x. |
CEIL(x), CEILING(x) |
Smallest integer ≥ x. |
MOD(x, y) |
Remainder of x divided by y. |
SIN(x), COS(x), TAN(x), COT(x) |
Trigonometric functions (radians). |
ASIN(x), ACOS(x), ATAN(x) |
Inverse trigonometric functions. |
DEGREES(x) |
Convert radians to degrees. |
RADIANS(x) |
Convert degrees to radians. |
Numbers combine with the arithmetic operators +, -, *, and /:
| Operator |
Description |
x + y |
Addition. |
x - y |
Subtraction. |
x * y |
Multiplication. |
x / y |
Division. |
-x |
Negation. |
match () limit 1 return 2 + 3 * 4 as a, 10 - 6 as b, mod(10, 4) as c, abs(-7) as d
match () limit 1 return sqrt(9) as `sqrt`, 9 / 3 as divideResult
Conditional expressions
CASE
CASE returns a value based on conditions, in searched form (evaluate independent predicates) or simple form (compare one expression to a series of values).
Searched form evaluates each WHEN predicate in turn:
match (m:Movie)
return m.Title as Title, case when m.Year < 2000 then 'C' else 'M' end as Era
Simple form compares one expression against each WHEN value:
match (m:Movie)
return m.Title as Title,
case m.Title
when 'T1' then 'A'
when 'T3' then 'G'
else 'O'
end as Name
| Title |
Name |
| T1 |
A |
| T2 |
O |
| T3 |
G |
Note
Every CASE expression must include an ELSE clause. A CASE without ELSE isn't supported.
Type conversion
CAST
CAST(value AS type) converts a value to another type, such as string, int64. It's required in two common situations.
Nested property access. When a property is reached through a nested or indexed expression, such as an element of a path or a member of a map, the result is a dynamic value whose type isn't known in advance. Cast it to the expected type before you compare or compute with it.
See here the supported types.
match p = (a:Person)-[:ACTED_IN]->(m:Movie)
return m.Title as Title, cast(nodes(p)[0].Born as int) as ActorBorn
| Title |
ActorBorn |
| T3 |
1956 |
| T2 |
1956 |
| T1 |
1956 |
| T1 |
1958 |
MATCH (p:Person)
RETURN p.Name || ', ' || CAST(p.Born as string) as nameAndYear
| nameAndYear |
| Tom, 1956 |
| Kevin, 1958 |
| Ron, 1954 |
| Julia, 1967 |
Aggregating on object keys. An aggregation key can't be an object (dynamic) value such as a node, edge, or property map. Convert the object value to a string first, using to_json_string(...) or CAST(... AS string).
match (p:Person)->(m:Movie)
return to_json_string(p), count(m) as participatedInMoviesCount
| to_json_string(p) |
participatedInMoviesCount |
| {"Name":"Tom", ... } |
4 |
| {"Name":"Kevin", ... } |
1 |
| {"Name":"Ron", ... } |
1 |
JSON functions
| Function |
Description |
PARSE_JSON_STRING(s) |
Parse a JSON string into an object or array. Access members with . or [index]. |
TO_JSON_STRING(x) |
Serialize a value (including a node or edge) to a JSON string. |
MATCH (n:Person {Name: 'Julia'})
RETURN TO_JSON_STRING(n) AS `json`
| json |
| {"Name":"Julia","Born":1967,"Label2":["Person ","Female ","BestActressAward "],"Label":"Person"} |
Tip
The result alias json is escaped because json is a reserved keyword
MATCH (p:Person)
limit 1
RETURN parse_json_string('{"a":"Michael", "b":"John"}'.a as string) AS name
MATCH (p:Person)
limit 1
RETURN cast(parse_json_string('{"a":1, "b":2}').a as integer) AS a
MATCH () limit 1 RETURN PARSE_JSON_STRING('[1,2,3]')[1] as second
Tip
When using parse_json_string() it might be needed to cast the retrieved value from json if a specific type is needed
List and Map functions and predicates
| Function |
Description |
SIZE(list) |
Number of elements in a list. |
KEYS(element) |
Property names of a node, edge, or map, as a string list. |
l1 \|\| l2 |
Concatenate lists l1 and l2. |
value IN [list] |
True when value is a member of the list. |
x[i] |
Access a list or path element by zero-based position, or a map member by key. |
match () limit 1 return ["a", "b", "c"][1] as second
match () limit 1 return size([1, 2, 3]) as `size`
Tip
The result alias size is escaped because size is a reserved keyword
match () limit 1 return keys({"a":1, "b":2}) as my_keys
MATCH (p:Person)
WHERE p.Name IN ['Tom', 'Kevin']
RETURN p.Name as actor
match () limit 1 return ["a"] || ["b"] as lst
Date and Time functions
| Function |
Description |
ZONED_DATETIME(), CURRENT_TIMESTAMP |
Current UTC timestamp. |
ZONED_DATETIME("...") |
Parse a timestamp from a string. |
DURATION({...}) |
Duration from a map of units: days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds. Accepts RECORD type value. years and months aren't supported. |
DURATION_BETWEEN(start, end) |
Duration between two timestamps. |
match () limit 1 return duration ({minutes: 5}) as "5min"
match () limit 1 return duration ({minutes: 5, seconds:25}) as "5min25sec"
If nodes in the graph have a property such as event_timestamp of KQL type datetime, you can find all graph nodes with an event that occurred in the last 10 minutes, measured from now or from a specific timestamp:
MATCH (n) where n.event_timestamp < CURRENT_TIMESTAMP - duration({minutes:10}) return n
MATCH (n) where n.event_timestamp < zoned_datetime('2025-09-15 09:00:00.0') - duration({minutes:10}) return n
MATCH () limit 1
RETURN DURATION_BETWEEN(zoned_datetime('2025-09-15 09:00:00.0'), zoned_datetime()) AS Elapsed
Note
The engine operates in UTC.
Graph and path functions
| Function |
Description |
LABELS(element) |
Labels of a node or edge, as a list. |
ELEMENT_ID(node) |
Identifier of a node. Edges aren't supported. |
NODES(path) |
Nodes of a path, as a list. |
EDGES(path), RELATIONSHIPS(path) |
Edges of a path, as a list. |
PATH_LENGTH(path) |
Number of edges (hops) in a path. |
match (m: Movie) limit 1 return labels(m) as lbls
match p = (n:Person)-[e: ACTED_IN]->(m: Movie) return p, path_length(p), nodes(p), edges(p)
Aggregations
Aggregate functions summarize the matched rows. When an aggregate appears next to non-aggregated expressions, those expressions become the grouping keys.
| Function |
Description |
COUNT(x), COUNT(*) |
Number of values, or number of rows with COUNT(*). |
SUM(x) |
Sum of numeric values. |
AVG(x) |
Average of numeric values. |
MIN(x), MAX(x) |
Smallest and largest value. |
COLLECT_LIST(x) |
Gather values into a list. |
MATCH (p:Person)
RETURN COUNT(*) AS people, MIN(p.Born) AS earliest, MAX(p.Born) AS latest, SUM(p.Born) AS bornSum, AVG(p.Born) AS bornAvg
| people |
earliest |
latest |
bornSum |
bornAvg |
| 4 |
1954 |
1967 |
7835 |
1958.75 |
Count the actors in each movie:
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
RETURN m.Title as Movie, COUNT(*) AS ActorsCount
| Movie |
ActorsCount |
| T1 |
2 |
| T2 |
1 |
| T3 |
1 |
MATCH (n:Person)-[:ACTED_IN]->(m:Movie)
RETURN collect_list(distinct n.Name) as actors
Find how many movies each actor acted in:
MATCH (n:Person)-[:ACTED_IN]->(m:Movie)
RETURN TO_JSON_STRING(n) as actor, count(m) as moviesCount
| actor |
moviesCount |
| {"Name":"Tom", ... ,"Label":"Person"} |
3 |
| {"Name":"Kevin", ... ,"Label":"Person"} |
1 |
Note
To group by or aggregate a node, edge, or path, first convert it to a string with TO_JSON_STRING() or CAST(object AS string), because objects can't be used as grouping keys directly.
For more, see Aggregations in the GQL guide.
Predicates
Comparison operators compare two scalar values and return a Boolean. They apply to scalar values, not to nodes or edges.
| Operator |
Description |
x = y |
Equal. |
x <> y |
Not equal. |
x < y, x <= y |
Less than, less than or equal. |
x > y, x >= y |
Greater than, greater than or equal. |
Other operators:
| Predicate |
Description |
value IN [list] |
True when value is a member of the list. |
match (p:Person)
where p.Name in ['Tom', 'Julia']
return p.Name as name
Negate the test with NOT to keep only values that are absent from the list:
match (p:Person)
where not p.Name in ['Tom', 'Kevin', 'Ron']
return p.Name as name
Other predicates:
| Predicate |
Description |
expr IS NULL, expr IS NOT NULL |
Test for null. string type can't be null |
expr IS [NOT] TRUE, expr IS [NOT] FALSE |
Test a Boolean expression. |
NOT expr |
Negate a Boolean condition. |
MATCH (p:Person)
WHERE p.Name IN ['Tom', 'Kevin'] AND p.Born IS NOT NULL
RETURN p.Name as name
It's possible to use IS TRUE or IS FALSE to test the result of a Boolean expression:
MATCH (p:Person)
WHERE (p.Born > 1960) IS TRUE
RETURN p.Name
Related content