Coauthors: Idris Motiwala, and Justin Fine
January–August 2026 updates expand how users find, inspect, compose, and analyze connections.
Organizations use graph data to understand how information moves between systems, how services depend on one another, how conversations develop, and how people or organizations relate. Graph Query Language (GQL) in Microsoft Fabric Graph helps users explore and analyze those connections with standardized query patterns.
From January through August 2026, new GQL capabilities made it easier to control traversals, inspect paths, compose multistage queries, summarize connected data, and work with complex values. These improvements help analysts express more graph questions in a single query and give developers finer control over query behavior. The following sections explain where each capability is useful and show the associated syntax.
Find and control paths
Shortest paths with ANY SHORTEST
When several paths connect two entities, many applications need one shortest path rather than every possible path. ANY SHORTEST makes that intent explicit. This is useful for dependency analysis, recommendations, network routing, and investigations where fewer intermediate steps are preferred.
MATCH ANY SHORTEST ({id: 1})->{,2}(d)
RETURN d.id AS dst
Quantified edge patterns
Quantified edge patterns repeat a complete relationship pattern and can apply conditions to intermediate nodes. In the following example, each repeated step requires the source person to use Chrome. This gives developers more control than repeating only an edge pattern.
MATCH p=(a:Person {id: 987})((x)-[k:knows]->() WHERE x.browserUsed = 'Chrome'){2}(b:Person)
FOR n IN NODES(p) WITH OFFSET off
RETURN n.browserUsed
ORDER BY a.id, b.id, off
LIMIT 12
Complete path modes
Path modes define whether a traversal can revisit nodes or edges.
- WALK permits repetition.
- TRAIL prevents repeated edges.
- SIMPLE prevents repeated interior nodes.
- ACYCLIC prevents any repeated node.
- DIFFERENT EDGES prevent one edge from satisfying more than one edge variable in the match.
These choices help query results reflect the meaning of a route, hierarchy, or dependency chain.
MATCH WALK (:Person {firstName: "Juliana"})-[:studyAt]->(:University)<-[:studyAt]-(p:Person)
RETURN p.firstName AS name MATCH TRAIL (:Person {firstName: "Juliana"})-[:studyAt]->(:University)<-[:studyAt]-(p:Person)
RETURN p.firstName AS name MATCH SIMPLE (x)->{2}(y)
RETURN COUNT(*) AS path_count MATCH ACYCLIC (x:`node` {id: 1})->(y)->(z)
RETURN x.id, y.id, z.id
ORDER BY x.id, y.id, z.id MATCH DIFFERENT EDGES (p:Person {name: 'Keanu Reeves'})-[e:ACTED_IN]->(m:Movie)
RETURN m.title AS movie
Unbounded variable-length path patterns
Variable-length paths previously required a maximum hop count. Unbounded quantifiers allow the graph structure to determine the traversal depth when no meaningful fixed limit exists. The example follows one or more relationships, while ACYCLIC prevents the traversal from visiting the same node twice. Unbounded refers to the path expression, not unlimited compute, so use selective starting points and test performance with representative graph density.
MATCH ACYCLIC ()-[]->{1,}()
RETURN COUNT(*) AS total
Inspect paths and graph elements
NODES, EDGES, and INNER_NODES
These functions expose the contents of a matched path. NODES returns all nodes in the path, EDGES returns all relationships in the path, and INNER_NODES returns the intermediate nodes without the endpoints. Applications can use these results to explain lineage, dependencies, and investigative findings instead of returning only a destination.
MATCH p=({id: 1})-[]->{0,4}(z)
RETURN NODES(p) AS res_nodes,
INNER_NODES(p) AS res_inner_nodes
ORDER BY z.id
ELEMENT_ID
ELEMENT_ID returns the identity of a graph element. It is useful when an application must compare, track, or reference a specific node or edge independently of its business properties.
MATCH (x)
RETURN ELEMENT_ID(x) AS vid, x AS actual_id
ORDER BY x.id
LIMIT 5
SOURCE and DESTINATION
SOURCE and DESTINATION identify the endpoints of an edge. This makes directional checks and edge-centric analysis easier, especially when a query starts from a relationship rather than a node.
MATCH (x)-[e]->()
RETURN x.id, SOURCE(e).id AS s
ORDER BY e.src, e.dst
LIMIT 10 MATCH ()-[e]->(x)
RETURN false IN COLLECT_LIST(x = DESTINATION(e)) AS no
Compose larger queries
NEXT
NEXT passes the output of one query stage into the next, allowing analysts to express a multistep question in a single query. For example, they can calculate a measure, filter the result, traverse another relationship, and summarize the final result without moving intermediate data into application code.
MATCH (m:Message)-[:hasCreator]-(p:Person)
RETURN p, AVG(m.length) AS avg_msg_length GROUP BY p
NEXT
FILTER avg_msg_length > 100u
MATCH (p)-[:knows]->(:Person)
RETURN avg_msg_length, COUNT(*) AS connections
GROUP BY p, avg_msg_length
EXISTS subqueries
EXISTS answers a yes-no question about another graph pattern. It can filter rows or participate inside an aggregate without requiring the outer query to return the matching details.
MATCH (x)
WHERE EXISTS {
MATCH (y)
WHERE y.id = 5
RETURN y
}
RETURN x.id AS xid
ORDER BY xid MATCH (x)
RETURN COUNT(*) FILTER (
WHERE EXISTS { MATCH (x)-[]->(y) RETURN y }
) AS count_with_out
CALL subqueries
CALL runs a contained query for each current outer result. In the example, it calculates each node’s outgoing degree and returns that value with the node identifier, keeping the intermediate calculation contained within the query.
MATCH (x)
CALL {
MATCH (x)-[e]->(y)
RETURN COUNT(e) AS out_degree
}
RETURN x.id AS xid, out_degree
ORDER BY xid
OPTIONAL CALL
OPTIONAL CALL preserves the outer row when the contained query has no match. This supports enrichment scenarios where related information is useful but not required.
MATCH (x {id: 1})
OPTIONAL CALL {
MATCH (y)-[]->(x)
RETURN y.id AS yid
}
RETURN x.id AS xid, yid
ORDER BY yid
UNION DISTINCT
UNION DISTINCT combines compatible result sets and removes duplicate rows. It complements UNION ALL, which preserves duplicates, so the query can choose the correct set behavior.
MATCH () LIMIT 3
RETURN 42 AS x
UNION
MATCH () LIMIT 3
RETURN 100u AS x
Summarize connected data
Filtered and paged aggregates
Filtered aggregates calculate a summary over a selected subset. Paging controls such as LIMIT can be applied within the aggregate, giving developers precise control over which values contribute to the result.
MATCH (m:Movie)
RETURN COUNT(*) FILTER (WHERE m.released < 1980 LIMIT 10) AS filtered_count
Nested aggregations
Nested aggregation supports layered questions, such as finding the minimum of averages calculated across groups or paths. This reduces the need to move intermediate results into application code.
MATCH (a:`node`)-[e:`edge`]->{1,2}(b:`node`)
RETURN a.id AS id, MIN(AVG(e.weight)) AS min_average
GROUP BY id
COLLECT_ONE, COLLECT_LIST, and COLLECT_ELEMENTS
Collection functions retain values or graph elements for evaluation as a group. COLLECT_ONE selects one value, COLLECT_LIST builds a list, and COLLECT_ELEMENTS gathers graph elements. They are useful for path-level checks, ordered output, and analysis across repeated relationships.
MATCH (p:`node` {id: 1})-[e]->{2}(p1:`node` {id: 1})
RETURN (COLLECT_ONE(e.weight) IN [e[0].weight, e[1].weight]) AS contained MATCH ()-[e]->{1,2}()
RETURN COLLECT_LIST(ALL e.weight) AS w
ORDER BY w
LIMIT 20 MATCH ()-[a:ACTED_IN]->{0,4}()
WHERE SIZE(COLLECT_ELEMENTS(DISTINCT a.roles)) > 4
RETURN TO_JSON_STRING(a.roles) AS r
Work with values and text
Dynamic nested data
Support for dynamic nested data lets queries work with richer values that do not fit a flat property model. This is useful when graph entities contain structured application payloads, nested attributes, or evolving schemas.
CAST
CAST converts a value to a supported target type. Explicit conversion makes comparisons and calculations more predictable when source data contains different numeric types.
RETURN CAST(42 AS DOUBLE) AS double_res,
CAST(42 AS UINT) AS uint_res,
CAST(42.5d AS INT) AS int_res
RANGE
RANGE creates a numeric sequence. A generated sequence can support iteration, testing, bucketing, and list-oriented calculations within a query.
RETURN RANGE(0, 4) AS res
POWER
POWER performs exponent calculations. It extends the numeric expressions available for scoring, weighting, and mathematical transformations.
RETURN POWER(-2, 3) AS res
NORMALIZE and IS NORMALIZED
Unicode text can have visually identical but technically different encodings. NORMALIZE converts text to a normalization form, while IS NORMALIZED checks its current form. This supports more consistent matching and grouping across multilingual data.
RETURN NORMALIZE('cafe\u0301') AS normalized_text
RETURN 'cafe\u0301' IS NFKD NORMALIZED AS is_normalized
Regular-expression functions
The MSFT.REGEXP functions match, count, locate, extract, and replace text patterns. They help prepare identifiers, names, codes, and descriptions before those values are compared or summarized.
RETURN MSFT.REGEXP_LIKE('café', 'caf.') AS x
RETURN MSFT.REGEXP_COUNT('abcabcabc', 'abc') AS n
RETURN MSFT.REGEXP_INSTR('hello world', 'world') AS p
RETURN MSFT.REGEXP_REPLACE('a1b2c3', '[0-9]', '#') AS s
RETURN MSFT.REGEXP_SUBSTR('abc123def', '[0-9]+') AS s
Design guidance
Use the narrowest pattern that answers the question. Start from selective nodes, specify relationship and node labels, and apply filters early. Use bounded traversal when the business question has a natural maximum. When depth is unknown, combine an unbounded path with an appropriate path mode and test it against representative graph density. Return only the properties or path elements the application requires.
Feature availability can vary by environment and release stage. Confirm the release stage and regional availability of each feature before publication. If availability differs by feature, identify the applicable release stage in each section.
Next steps
Start with a connected-data scenario such as lineage, dependency analysis, recommendations, investigations, or knowledge discovery. Identify the relationships the question must follow, choose the path mode and traversal depth that match the scenario, and then use composition and aggregation features to shape the result.