GQL query statements

Graph Query Language (GQL) lets you execute multiple lineargraph queries in one query. Each linear graph query generates results(the working table) and then passes those results to the next.

GQL supports the following building blocks, which can be composited into aGQL query based on thesyntax rules.

Language list

NameSummary
GQL syntaxCreates a graph query with the GQL syntax.
GRAPH clause Specifies a property graph to query.
CALL statement Executes an inline subquery over the working table.
FILTER statement Filters out rows in the query results that don't satisfy a specified condition.
FOR statement Unnests anARRAY-typed expression.
LET statement Defines variables and assigns values for later use in the current linear query statement.
LIMIT statementLimits the number of query results.
MATCH statementMatches data described by a graph pattern.
NEXT statementChains multiple linear query statements together.
OFFSET statementSkips a specified number of rows in the query results.
ORDER BY statementOrders the query results.
RETURN statementMarks the end of a linear query statement and returns the results.
SKIP statementSynonym for theOFFSET statement.
WITH statement Passes on the specified columns, optionally filtering, renaming, and transforming those results.
Set operationCombines a sequence of linear query statements with a set operation.
Graph hints Query hints, which make the query optimizer use a specific operator in the execution plan.

GQL syntax

graph_query:GRAPH clausemulti_linear_query_statementmulti_linear_query_statement:linear_query_statement  [    NEXTlinear_query_statement  ]  [...]linear_query_statement:  {simple_linear_query_statement    |composite_linear_query_statement  }composite_linear_query_statement:simple_linear_query_statementset_operatorsimple_linear_query_statement  [...]simple_linear_query_statement:primitive_query_statement  [...]

Description

Creates a graph query with the GQL syntax. The syntax rules define howto composite the building blocks of GQL into a query.

Definitions

  • primitive_query_statement: A statement inQuery statementsexcept for theNEXT statement.
  • simple_linear_query_statement: A list ofprimitive_query_statements thatends with aRETURN statement.
  • composite_linear_query_statement: A list ofsimple_linear_query_statements composited with theset operators.
  • linear_query_statement: A statement that's either asimple_linear_query_statement or acomposite_linear_query_statement.
  • multi_linear_query_statement: A list oflinear_query_statements chainedtogether with theNEXT statement.
  • graph_query: A GQL query that starts with aGRAPH clause,then follows with amulti_linear_query_statement.

GRAPH clause

GRAPHproperty_graph_namemulti_linear_query_statement

Description

Specifies a property graph to query. This clause must be added before the firstlinear query statement in a graph query.

Definitions

  • property_graph_name: The name of the property graph to query.
  • multi_linear_query_statement: A multi linear query statement. For moreinformation, seemulti_linear_query_statement inGQL syntax.

Examples

The following example queries theFinGraph property graph to findaccounts with incoming transfers and looks up their owners:

GRAPHFinGraphMATCH(:Account)-[:Transfers]->(account:Account)RETURNaccount,COUNT(*)ASnum_incoming_transfersGROUPBYaccountNEXTMATCH(account:Account)<-[:Owns]-(owner:Person)RETURNaccount.idASaccount_id,owner.nameASowner_name,num_incoming_transfers/*--------------------------------------------------+ | account_id | owner_name | num_incoming_transfers | +--------------------------------------------------+ | 7          | Alex       | 1                      | | 20         | Dana       | 1                      | | 6          | Lee        | 3                      | +--------------------------------------------------*/

CALL statement

Note: Syntax characters enclosed in double quotes ("") are literal andrequired.
[ OPTIONAL ] CALL ( [variable_name [ , ... ] ] ) "{"subquery "}"

Description

Executes aninline subquery over the working table.

Definitions

Details

TheCALL statement supports modular query design and the invocation of complexlogic in a graphquery.

When you use an inline subquery, you must use a variable scope list inparentheses() before the opening curly brace{ of the subquery. Thevariable scope list specifies which variables from the outer query scope thesubquery can access. An empty variable scope list() indicates thatthe subquery is self-contained and can't reference any variables from the outerscope.

TheOPTIONAL CALL clause ensures that the input row still appears even if theCALL statement produces no results for a given input row. In such cases, theCALL statement addsNULL values to the columns where it produced no output.

Column-naming rules

Queries that use theCALL statement must maintain the followingcolumn-naming rules for uniqueness:

  • Within the subquery output: Thecolumns returned by the inlinesubquery itself must have unique names. For a subquery, theRETURNstatement enforces name uniqueness.
  • Combined output: The final set of columns generated by the queryincludes columns from the input table and columns added by theCALLstatement. All final columns must have unique names. Forsubqueries, ensure that the column names in theRETURN statement don'tconflict with existing columns in the outer scope.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

Example: Call an inline subquery

The following example calls an inline subquery to find accounts owned by eachmatched personp. Multiple accounts for the same person are ordered by accountID.

GRAPHFinGraphMATCH(p:Person)CALL(p){MATCH(p)-[:Owns]->(a:Account)RETURNa.IdASaccount_IdORDERBYaccount_IdLIMIT2}RETURNp.nameASperson_name,account_IdORDERBYperson_name,account_Id;/*--------------------------+ | person_name | account_Id | +--------------------------+ | Alex        | 16         | | Dana        | 17         | | Dana        | 20         | | Lee         | 7          | +--------------------------*/

Notice that the example declares the outer-scoped node variablep (CALL (p))from theMATCH (p:Person) clause. This declaration enables the node variableto be redeclared ormultiply-declared in a path pattern of the subquery. IftheCALL statement doesn't declare the node variablep, then the redeclaredvariablep in the subquery is treated as a new variable, independent of theouter-scoped variable (not multiply-declared), and returns different results.

GRAPHFinGraphMATCH(p:Person)-- Outer-scoped variable `p`CALL(){-- `p` not declaredMATCH(p)-[:Owns]->(a:Account)-- Inner-scoped variable `p`, independent of outer-scoped `p`RETURNa.IdASaccount_IdORDERBYaccount_IdLIMIT2}RETURNp.nameASperson_name,account_IdORDERBYperson_name,account_Id;-- Altered query results/*--------------------------+ | person_name | account_Id | +--------------------------+ | Alex        |          7 | | Alex        |         16 | | Dana        |          7 | | Dana        |         16 | | Lee         |          7 | | Lee         |         16 | +--------------------------*/

Additionally, the following version of the query fails because the declaredvariableId isn't a node or an edge variable. You can redeclare only node oredge variables in subqueries.

GRAPHFinGraphMATCH(p:Person{Id:2})LETId=p.IdCALL(Id){-- Non-node, non-edge variable `Id` declaredMATCH(p)-[:Owns]->(a:Account)RETURNa.Id-- Not allowed, outer-scoped `Id` isn't a node or edge variable, so you can't redeclare it.ORDERBYa.IdLIMIT2}RETURNp.nameASperson_name,Id;/*ERROR: generic::invalid_argument: Variable name: Id already exists [at 7:3]  RETURN a.Id*/

Example: Call an inline subquery with aggregation

The following query calls an inline subquery that aggregates the number ofaccountsa for each matched personp:

GRAPHFinGraphMATCH(p:Person)CALL(p){MATCH(p)-[:Owns]->(a:Account)RETURNcount(a)ASnum_accounts}RETURNp.name,num_accountsORDERBYnum_accountsDESC,p.name;/*-----------------------+ | name   | num_accounts | +-----------------------+ | Dana   | 2            | | Alex   | 1            | | Lee    | 1            | +-----------------------*/

Example: UseOPTIONAL to includeNULL row values

The following query finds the two most recent account transferst for eachpersonp. TheOPTIONAL clause includes rows for which the TVF or subqueryproduces no output. Rows with no output returnNULL values. Without theOPTIONAL clause, rows with no output are excluded from the results.

GRAPHFinGraphMATCH(p:Person)OPTIONALCALL(p){MATCH(p)-[:Owns]->(a:Account)-[t:Transfers]->()RETURNa.IdASaccount_id,t.amountAStransfer_amount,DATE(t.create_time)AStransfer_dateORDERBYtransfer_dateDESCLIMIT2}RETURNp.name,account_id,transfer_amount,transfer_dateORDERBYp.name,transfer_dateDESC;/*-------------------------------------------------------+ | name   | account_id | transfer_amount | transfer_date | +-------------------------------------------------------+ | Alex   | NULL       | NULL            | NULL          | | Alex   | 7          | 300             | 2020-08-29    | | Dana   | 20         | 200             | 2020-10-17    | | Dana   | 20         | 500             | 2020-10-04    | | Lee    | 16         | 300             | 2020-09-25    | +-------------------------------------------------------*/

Example: UseRETURN to rename conflicting subquery column names

The following query uses theRETURN alias in the subquery to avoid conflictingwith thep.Id column.

GRAPHFinGraphMATCH(p:Person{Id:1})CALL(p){MATCH(p)-[:Owns]->(a:Account)RETURNa.IdASaccount_Id}RETURNp.IdASperson_Id,account_Id;/*------------------------+ | person_Id | account_Id | +------------------------+ | 1         | 16         | +------------------------*/

Example: Filter, order, and limit subquery results

The following query finds the top three largest transfers over 50 dollar amountsfor each person.

GRAPHFinGraphMATCH(p:Person)CALL(p){MATCH(p)-[:Owns]->(a:Account)-[t:Transfers]->()WHEREt.amount >50RETURNa.IdASaccount_id,t.amountORDERBYt.amountDESCLIMIT3}RETURNp.name,account_id,amountORDERBYp.name,amountDESC;/*------------------------------+ | name   | account_id | amount | +------------------------------+ | Alex   | NULL       | NULL   | | Dana   | 17         | 80     | | Dana   | 20         | 100    | | Dana   | 17         | 60     | | Lee    | 7          | 200    | | Lee    | 7          | 150    | +------------------------------*/

Example: Use an empty scope list in a subquery

The following subquery counts allPerson nodes. Thetotal_persons value isthe same for all output rows because the subquery in theCALL () statement isempty and doesn't depend on any variables from the outer scope.

GRAPHFinGraphMATCH(p:Person)CALL(){MATCH(n:Person)RETURNcount(n)AStotal_persons}RETURNp.name,total_personsORDERBYp.name;/*------------------------+ | name   | total_persons | +------------------------+ | Alex   | 3             | | Dana   | 3             | | Lee    | 3             | +------------------------*/

Example: Call nested subqueries with variable scoping

The following query uses nested subqueries with scoped variables. The queryfinds the number of transfers for each account, but only for transfers toaccounts owned by the original personp.

GRAPHFinGraphMATCH(p:Person{Id:2})CALL(p){MATCH(p)-[:Owns]->(a:Account)OPTIONALCALL(p,a){MATCH(a)-[t:Transfers]->(other:Account),(p)-[:Owns]->(other)RETURNcount(t)ASnum_internal_transfers}RETURNa.IdASaccount_Id,COALESCE(num_internal_transfers,0)ASinternal_transfers}RETURNp.name,account_Id,internal_transfersORDERBYaccount_Id;/*------------------------------------------+ | name   | account_Id | internal_transfers | +------------------------------------------+ | Dana   | 20         | 0                  | +------------------------------------------*/

FILTER statement

FILTER [ WHERE ]bool_expression

Description

Filters out rows in the query results that don't satisfy a specified condition.

Definitions

  • bool_expression: A boolean expression. Only rows whosebool_expressionevaluates toTRUE are included. Rows whosebool_expression evaluates toNULL orFALSE are discarded.

Details

TheFILTER statement can reference columns in the working table.

The syntax for theFILTER statement is similar to the syntax for thegraph patternWHERE clause, but they are evaluateddifferently. TheFILTER statement is evaluated after the previous statement.TheWHERE clause is evaluated as part of the containing statement.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

In the following query, people withId = 1 are excluded from theresults table:

GRAPHFinGraphMATCH(p:Person)-[o:Owns]->(a:Account)FILTERp.Id <>1RETURNp.name,a.IdASaccount_id/*--------+------------+ | name   | account_id | +--------+------------+ | "Dana" | 20         | | "Lee"  | 16         | +--------+------------*/

WHERE is an optional keyword that you can include in aFILTER statement.The following query is semantically identical to the previous query:

GRAPHFinGraphMATCH(p:Person)-[o:Owns]->(a:Account)FILTERWHEREp.Id <>1RETURNp.name,a.IdASaccount_id/*--------+------------+ | name   | account_id | +--------+------------+ | "Dana" |         20 | | "Lee"  |         16 | +--------+------------*/

In the following example,FILTER follows an aggregation step withgrouping. Semantically, it's similar to theHAVING clause in SQL:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(dest:Account)RETURNsource,COUNT(e)ASnum_transfersGROUPBYsourceNEXTFILTERWHEREnum_transfers >1RETURNsource.idASsource_id,num_transfers/*---------------------------+ | source_id | num_transfers | +---------------------------+ | 7         | 2             | | 20        | 2             | +---------------------------*/

In the following example, an error is produced becauseFILTER referencesm, which isn't in the working table:

-- Error: m doesn't existGRAPHFinGraphMATCH(p:Person)-[o:Owns]->(a:Account)FILTERWHEREm.Id <>1RETURNp.name

In the following example, an error is produced because even thoughp is in theworking table,p doesn't have a property calleddate_of_birth:

-- ERROR: date_of_birth isn't a property of pGRAPHFinGraphMATCH(p:Person)-[o:Owns]->(a:Account)FILTERWHEREp.date_of_birth <'1990-01-10'RETURNp.name

FOR statement

FORelement_name INarray_expression  [with_offset_clause ]with_offset_clause:  WITH OFFSET [ ASoffset_name ]

Description

Unnests anARRAY-typed expression and joins the result with the current working table.

Definitions

  • array_expression: AnARRAY-typed expression.
  • element_name: The name of the element column. The name can't be the nameof a column that already exists in the current linear query statement.
  • offset_name: The name of the offset column. The name can't be the name ofa column that already exists in the current linear query statement. If notspecified, the default isoffset.

Details

TheFOR statement expands the working table by defining a new column for theelements ofarray_expression, with an optional offset column. The cardinalityof the working table might change as a result.

TheFOR statement can reference columns in the working table.

TheFOR statement evaluation is similar to theUNNEST operator.

TheFOR statement doesn't preserve order.

And empty orNULLarray_expression produces zero rows.

The keywordWITH following theFOR statement is always interpreted as thebeginning ofwith_offset_clause. If you want to use theWITH statementfollowing theFOR statement, you should fully qualify theFOR statement withwith_offset_clause, or use theRETURN statement instead of theWITHstatement.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

In the following query, there are three rows in the working table prior to theFOR statement. After theFOR statement, each row is expanded into two rows,one perelement value from the array.

GRAPHFinGraphMATCH(p:Person)-[o:Owns]->(a:Account)FORelementin["all","some"]WITHOFFSETRETURNp.Id,elementasalert_type,offsetORDERBYp.Id,element,offset/*----------------------------+ | Id   | alert_type | offset | +----------------------------+ | 1    | all        | 0      | | 1    | some       | 1      | | 2    | all        | 0      | | 2    | some       | 1      | | 3    | all        | 0      | | 3    | some       | 1      | +----------------------------*/

In the following query, there are two rows in the working table prior to theFOR statement. After theFOR statement, each row is expanded into adifferent number of rows, based on the value ofarray_expression for that row.

GRAPHFinGraphMATCH(p:Person)-[o:Owns]->(a:Account)FILTERWHEREp.Id <>1FORelementinGENERATE_ARRAY(1,p.Id)RETURNp.Id,elementORDERBYp.Id,element/*----------------+ | Id   | element | +----------------+ | 2    | 1       | | 2    | 2       | | 3    | 1       | | 3    | 2       | | 3    | 3       | +----------------*/

In the following query, there are three rows in the working table prior to theFOR statement. After theFOR statement, no row is produced becausearray_expression is an empty array.

-- No rows producedGRAPHFinGraphMATCH(p:Person)FORelementin[]WITHOFFSETASoffRETURNp.name,element,off

In the following query, there are three rows in the working table prior to theFOR statement. After theFOR statement, no row is produced becausearray_expression is aNULL array.

-- No rows producedGRAPHFinGraphMATCH(p:Person)FORelementinCAST(NULLASARRAY<STRING>)WITHOFFSETRETURNp.name,element,offset

In the following example, an error is produced becauseWITH is used directlyAfter theFOR statement. The query can be fixed by addingWITH OFFSET aftertheFOR statement, or by usingRETURN directly instead ofWITH.

-- Error: Expected keyword OFFSET but got identifier "element"GRAPHFinGraphFORelementin[1,2,3]WITHelementascolRETURNcolORDERBYcol
GRAPHFinGraphFORelementin[1,2,3]WITHOFFSETWITHelementascolRETURNcolORDERBYcol/*-----+ | col | +-----+ | 1   | | 2   | | 3   | +-----*/

LET statement

LETlinear_graph_variable[, ...]linear_graph_variable:variable_name =value

Description

Defines variables and assigns values to them for later use in the currentlinear query statement.

Definitions

  • linear_graph_variable: The variable to define.
  • variable_name: The name of the variable.
  • value: A scalar expression that represents the value of the variable.The names referenced by this expression must be in the incoming workingtable.

Details

LET doesn't change the cardinality of the working table nor modify itsexisting columns.

The variable can only be used in the current linear query statement. To use itin a following linear query statement, you must include it in theRETURNstatement as a column.

You can't define and reference a variable within the sameLET statement.

You can't redefine a variable with the same name.

You can use horizontal aggregate functions in this statement. To learn more, seeHorizontal aggregate function calls in GQL.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

In the following graph query, the variablea is defined and then referencedlater:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=sourceRETURNa.idASa_id/*------+ | a_id | +------+ | 20   | | 7    | | 7    | | 20   | | 16   | +------*/

The followingLET statement in the second linear query statement is validbecausea is defined and returned from the first linear query statement:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=sourceRETURNaNEXTLETb=a-- Valid: 'a' is defined and returned from the linear query statement above.RETURNb.idASb_id/*------+ | b_id | +------+ | 20   | | 7    | | 7    | | 20   | | 16   | +------*/

The followingLET statement in the second linear query statement is invalidbecausea isn't returned from the first linear query statement.

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=sourceRETURNsource.idNEXTLETb=a-- ERROR: 'a' doesn't exist.RETURNb.idASb_id

The followingLET statement is invalid becausea is defined and thenreferenced in the sameLET statement:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=source,b=a-- ERROR: Can't define and reference 'a' in the same operation.RETURNa

The followingLET statement is valid becausea is defined first and thenreferenced afterwards:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=sourceLETb=aRETURNb.idASb_id/*------+ | b_id | +------+ | 20   | | 7    | | 7    | | 20   | | 16   | +------*/

In the following examples, theLET statements are invalid becausea isredefined:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=source,a=destination-- ERROR: 'a' has already been defined.RETURNa.idASa_id
GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=sourceLETa=destination-- ERROR: 'a' has already been defined.RETURNa.idASa_id

In the following examples, theLET statements are invalid becauseb isredefined:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=sourceLETb=destinationRETURNa,bNEXTMATCH(a)LETb=a-- ERROR: 'b' has already been defined.RETURNb.id

The followingLET statement is valid because althoughb is defined in thefirst linear query statement, it's not passed to the second linear querystatement:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)LETa=sourceLETb=destinationRETURNaNEXTMATCH(a)LETb=aRETURNb.id/*------+ | b_id | +------+ | 20   | | 7    | | 7    | | 20   | | 16   | +------*/

LIMIT statement

LIMITcount

Description

Limits the number of query results.

Definitions

  • count: A non-negativeINT64 value that represents the number ofresults to produce. For more information,see theLIMIT andOFFSET clauses.

Details

TheLIMIT statement can appear before theRETURN statement. You can also useit as a qualifying clause in theRETURN statement.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

The following example uses theLIMIT statement to limit the query results tothree rows:

GRAPHFinGraphMATCH(source:Account)-[e:Transfers]->(destination:Account)ORDERBYsource.IdLIMIT3RETURNsource.Id,source.nick_name/*---------+---------------+ | Id      | nick_name     | +---------+---------------+ | 7       | Vacation fund | | 7       | Vacation fund | | 16      | Vacation fund | +-------------------------*/

The following query finds the account and its owner with the most outgoingtransfers to a blocked account:

GRAPHFinGraphMATCH(src_account:Account)-[transfer:Transfers]->(dst_account:Account{is_blocked:true})RETURNsrc_account,COUNT(transfer)astotal_transfersORDERBYtotal_transfersLIMIT1NEXTMATCH(src_account:Account)<-[owns:Owns]-(owner:Person)RETURNsrc_account.idASaccount_id,owner.nameASowner_name/*-------------------------+ | account_id | owner_name | +-------------------------+ | 20         | Dana       | +-------------------------*/

MATCH statement

[ OPTIONAL ] MATCH [match_hint ]graph_pattern

Description

Matches data described by a graph pattern. You can have zero or moreMATCHstatements in a linear query statement.

Definitions

  • MATCH graph_pattern: The graph pattern to match. For more information,seeMATCH graph pattern definition.
  • OPTIONAL MATCH graph_pattern: The graph pattern to optionally match. If thereare missing parts in the pattern, the missing parts are represented byNULLvalues. For more information, seeOPTIONAL MATCH graph pattern definition.
  • match_hint: A hint that makes the query optimizer use a specific statement inthe execution plan. This statement supports graph hints. For moreinformation, seeGraph hints.

Details

TheMATCH statement joins the incoming working table with the matchedresult with eitherINNER JOIN orCROSS JOIN semantics.

TheINNER JOIN semantics is used when the working table and matched resulthave variables in common. In the following example, theINNER JOINsemantics is used becausefriend is produced by bothMATCH statements:

MATCH(person:Person)-[:knows]->(friend:Person)MATCH(friend)-[:knows]->(otherFriend:Person)

TheCROSS JOIN semantics is used when the incoming working table and matchedresult have no variables in common. In the following example, theCROSS JOINsemantics is used becauseperson1 andfriend exist in the result of thefirstMATCH statement, but not the second one:

MATCH(person1:Person)-[:knows]->(friend:Person)MATCH(person2:Person)-[:knows]->(otherFriend:Person)

Examples

Note: The examples in this section reference a property graph calledFinGraph.

The following query matches allPerson nodes and returns the name and ID ofeach person:

GRAPHFinGraphMATCH(p:Person)RETURNp.name,p.id/*-----------+ | name | id | +-----------+ | Alex | 1  | | Dana | 2  | | Lee  | 3  | +-----------*/

The following query matches allPerson andAccount nodes and returns theirlabels and ID:

GRAPHFinGraphMATCH(n:Person|Account)RETURNLABELS(n)ASlabel,n.id/*----------------+ | label     | id | +----------------+ | [Account] | 7  | | [Account] | 16 | | [Account] | 20 | | [Person]  | 1  | | [Person]  | 2  | | [Person]  | 3  | +----------------*/

The following query matches allAccount nodes that aren't blocked:

GRAPHFinGraphMATCH(a:Account{is_blocked:false})RETURNa.id/*----+ | id | +----+ | 7  | | 20 | +----*/

The following query matches allPerson nodes that have abirthday less than1990-01-10:

GRAPHFinGraphMATCH(p:PersonWHEREp.birthday <'1990-01-10')RETURNp.name/*------+ | name | +------+ | Dana | | Lee  | +------*/

The following query matches allOwns edges:

GRAPHFinGraphMATCH-[e:Owns]->RETURNe.id/*----+ | id | +----+ | 1  | | 3  | | 2  | +----*/

The following query matches allOwns edges created within a specific period oftime:

GRAPHFinGraphMATCH-[e:OwnsWHEREe.create_time >'2020-01-14'ANDe.create_time <'2020-05-14']->RETURNe.id/*----+ | id | +----+ | 2  | | 3  | +----*/

The following query matches allTransfers edges where a blocked account isinvolved in any direction:

GRAPHFinGraphMATCH(account:Account)-[transfer:Transfers]-(:Account{is_blocked:true})RETURNtransfer.order_number,transfer.amount/*--------------------------+ | order_number    | amount | +--------------------------+ | 304330008004315 | 300    | | 304120005529714 | 100    | | 103650009791820 | 300    | | 302290001255747 | 200    | +--------------------------*/

The following query matches allTransfers initiated from anAccount owned byPerson withid equal to2:

GRAPHFinGraphMATCH(p:Person{id:2})-[:Owns]->(account:Account)-[t:Transfers]->(to_account:Account)RETURNp.idASsender_id,to_account.idASto_id/*-------------------+ | sender_id | to_id | +-------------------+ | 2         | 7     | | 2         | 16    | +-------------------*/

The following query matches all the destinationAccounts one to threetransfers away from a sourceAccount withid equal to7, other than thesource itself:

GRAPHFinGraphMATCH(src:Account{id:7})-[e:Transfers]->{1,3}(dst:Account)WHEREsrc!=dstRETURNARRAY_LENGTH(e)AShops,dst.idASdestination_account_id/*-------------------------------+ | hops | destination_account_id | +-------------------------------+ | 1    | 16                     | | 3    | 16                     | | 3    | 16                     | | 1    | 16                     | | 2    | 20                     | | 2    | 20                     | +-------------------------------*/

The following query matches paths betweenAccount nodes with one to twoTransfers edges through intermediate accounts that are blocked:

GRAPHFinGraphMATCH(src:Account)((a:Account)-[:Transfers]->(b:Account{is_blocked:true})WHEREa!=b){1,2}-[:Transfers]->(dst:Account)RETURNsrc.idASsource_account_id,dst.idASdestination_account_id/*--------------------------------------------+ | source_account_id | destination_account_id | +--------------------------------------------+ | 7                 | 20                     | | 7                 | 20                     | | 20                | 20                     | +--------------------------------------------*/

The following query finds unique reachable accounts which are one or twotransfers away from a givenAccount node:

GRAPHFinGraphMATCHANY(src:Account{id:7})-[e:Transfers]->{1,2}(dst:Account)LETids_in_path=ARRAY_CONCAT(ARRAY_AGG(e.Id),[dst.Id])RETURNsrc.idASsource_account_id,dst.idASdestination_account_id,ids_in_path/*----------------------------------------------------------+ | source_account_id | destination_account_id | ids_in_path | +----------------------------------------------------------+ | 7                 | 16                     | [7, 16]     | | 7                 | 20                     | [7, 16, 20] | +----------------------------------------------------------*/

The following query matches allPerson nodes and optionally matches theblockedAccount owned by thePerson. The missing blockedAccount isrepresented asNULL:

GRAPHFinGraphMATCH(n:Person)OPTIONALMATCH(n:Person)-[:Owns]->(a:Account{is_blocked:TRUE})RETURNn.name,a.idASblocked_account_id/*--------------+ | name  | id   | +--------------+ | Lee   | 16   | | Alex  | NULL | | Dana  | NULL | +--------------*/

NEXT statement

NEXT
Description

Chains multiple linear query statements together.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

The following linear query statements are chained by theNEXT statement:

GRAPHFinGraphMATCH(:Account)-[:Transfers]->(account:Account)RETURNaccount,COUNT(*)ASnum_incoming_transfersGROUPBYaccountNEXTMATCH(account:Account)<-[:Owns]-(owner:Person)RETURNaccount.idASaccount_id,owner.nameASowner_name,num_incoming_transfersNEXTFILTERnum_incoming_transfers <2RETURNaccount_id,owner_name/*-------------------------+ | account_id | owner_name | +-------------------------+ | 7          | Alex       | | 20         | Dana       | +-------------------------*/

OFFSET statement

OFFSETcount

Description

Skips a specified number of rows in the query results.

Definitions

  • count: A non-negativeINT64 value that represents the number ofrows to skip. For more information,see theLIMIT andOFFSET clauses.

Details

TheOFFSET statement can appear anywhere in a linear query statement beforetheRETURN statement.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

In the following example, the first two rows aren't included in the results:

GRAPHFinGraphMATCH(p:Person)OFFSET2RETURNp.name,p.id/*-----------+ | name | id | +-----------+ | Lee  | 3  | +-----------*/

ORDER BY statement

ORDER BYorder_by_specification[, ...]order_by_specification:expression  [ COLLATEcollation_specification ]  [ { ASC | ASCENDING | DESC | DESCENDING } ]

Description

Orders the query results.

Definitions

  • expression: The sort criterion for the result set. For more information,see theORDER BY clause.
  • COLLATE collation_specification: The collation specification forexpression. For more information, see theORDER BY clause.
  • ASC | ASCENDING | DESC | DESCENDING: The sort order, which can be eitherascending or descending. The following options are synonymous:

    • ASC andASCENDING

    • DESC andDESCENDING

    For more information about sort order, see theORDER BY clause.

Details

Ordinals aren't supported in theORDER BY statement.

TheORDER BY statement is ignored unless it's immediately followed by theLIMIT orOFFSET statement.

If you would like to applyORDER BY to what is inRETURN statement, use theORDER BY clause inRETURN statement. For more information, seeRETURN statement.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

The following query sorts the results by thetransfer.amountvalues in descending order:

GRAPHFinGraphMATCH(src_account:Account)-[transfer:Transfers]->(dst_account:Account)ORDERBYtransfer.amountDESCLIMIT3RETURNsrc_account.idASaccount_id,transfer.amountAStransfer_amount/*------------------------------+ | account_id | transfer_amount | +------------------------------+ | 20         | 500             | | 7          | 300             | | 16         | 300             | +------------------------------*/
GRAPHFinGraphMATCH(src_account:Account)-[transfer:Transfers]->(dst_account:Account)ORDERBYtransfer.amountDESCOFFSET1RETURNsrc_account.idASaccount_id,transfer.amountAStransfer_amount/*------------------------------+ | account_id | transfer_amount | +------------------------------+ | 7          | 300             | | 16         | 300             | | 20         | 200             | | 7          | 100             | +------------------------------*/

If you don't include theLIMIT orOFFSET statement right after theORDER BY statement, the effect ofORDER BY is discarded and the result isunordered.

-- Warning: The transfer.amount values aren't sorted because the-- LIMIT statement is missing.GRAPHFinGraphMATCH(src_account:Account)-[transfer:Transfers]->(dst_account:Account)ORDERBYtransfer.amountDESCRETURNsrc_account.idASaccount_id,transfer.amountAStransfer_amount/*------------------------------+ | account_id | transfer_amount | +------------------------------+ | 7          | 300             | | 7          | 100             | | 16         | 300             | | 20         | 500             | | 20         | 200             | +------------------------------*/
-- Warning: Using the LIMIT clause in the RETURN statement, but not immediately-- after the ORDER BY statement, also returns the unordered transfer.amount-- values.GRAPHFinGraphMATCH(src_account:Account)-[transfer:Transfers]->(dst_account:Account)ORDERBYtransfer.amountDESCRETURNsrc_account.idASaccount_id,transfer.amountAStransfer_amountLIMIT10/*------------------------------+ | account_id | transfer_amount | +------------------------------+ | 7          | 300             | | 7          | 100             | | 16         | 300             | | 20         | 500             | | 20         | 200             | +------------------------------*/

RETURN statement

RETURN*
RETURN  [ { ALL | DISTINCT } ]return_item[, ... ]  [group_by_clause ]  [order_by_clause ]  [limit_and_offset_clauses ]return_item:  {expression [ ASalias ] |* }limit_and_offset_clauses:  {limit_clause    |offset_clause    |offset_clauselimit_clause  }

Description

Marks the end of a linear query statement and returns the results. Only oneRETURNstatement is allowed in a linear query statement.

Definitions

  • *: Returns all columns in the current working table.
  • return_item: A column to include in the results.
  • ALL: Returns all rows. This is equivalent to not using any prefix.
  • DISTINCT: Duplicate rows are discarded and only the remaining distinctrows are returned. This deduplication takes place after any aggregationis performed.
  • expression: An expression that represents a column to produce.Aggregation is supported.
  • alias: An alias forexpression.
  • group_by_clause: Groups the current rows of the working table, using theGROUP BY clause.
  • order_by_clause: Orders the current rows in alinear query statement, using theORDER BY clause.
  • limit_clause: Limits the number of current rows in alinear query statement, using theLIMIT clause.
  • offset_clause: Skips a specified number of rows in a linear query statement,using theOFFSET clause.

Details

If any expression performs aggregation, and noGROUP BY clause isspecified, all groupable items from the return list are used implicitly asgrouping keys.

Ordinals aren't supported in theORDER BY andGROUP BY clauses.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

The following query returnsp.name andp.id:

GRAPHFinGraphMATCH(p:Person)RETURNp.name,p.id/*-----------+ | name | id | +-----------+ | Alex | 1  | | Dana | 2  | | Lee  | 3  | +-----------*/

In the following example, the first linear query statement returns all columnsincludingp,a,b, andc. The second linear query statement returns thespecifiedp.name andd columns:

GRAPHFinGraphMATCH(p:Person)LETa=1,b=2,c=3RETURN*NEXTRETURNp.name,(a+b+c)ASd/*----------+ | name | d | +----------+ | Alex | 6 | | Dana | 6 | | Lee  | 6 | +----------*/

The following query returns distinct rows:

GRAPHFinGraphMATCH(src:Account{id:7})-[e:Transfers]->{1,3}(dst:Account)RETURNDISTINCTARRAY_LENGTH(e)AShops,dst.idASdestination_account_id/*-------------------------------+ | hops | destination_account_id | +-------------------------------+ | 3    | 7                      | | 1    | 16                     | | 3    | 16                     | | 2    | 20                     | +-------------------------------*/

In the following example, the first linear query statement returnsaccount andaggregatednum_incoming_transfers per account. The second statement returnssorted result.

GRAPHFinGraphMATCH(:Account)-[:Transfers]->(account:Account)RETURNaccount,COUNT(*)ASnum_incoming_transfersGROUPBYaccountNEXTMATCH(account:Account)<-[:Owns]-(owner:Person)RETURNowner.nameASowner_name,num_incoming_transfersORDERBYnum_incoming_transfersDESC/*-------------------------------------+ | owner_name | num_incoming_transfers | +-------------------------------------+ | Lee        | 3                      | | Alex       | 1                      | | Dana       | 1                      | +-------------------------------------*/

In the following example, theLIMIT clause in theRETURN statementreduces the results to one row:

GRAPHFinGraphMATCH(p:Person)RETURNp.name,p.idLIMIT1/*-----------+ | name | id | +-----------+ | Alex | 1  | +-----------*/

In the following example, theOFFSET clause in theRETURN statementskips the first row:

GRAPHFinGraphMATCH(p:Person)RETURNp.name,p.idOFFSET1/*-----------+ | name | id | +-----------+ | Dana | 2  | | Lee  | 3  | +-----------*/

In the following example, theOFFSET clause in theRETURN statementskips the first row, then theLIMIT clause reduces theresults to one row:

GRAPHFinGraphMATCH(p:Person)RETURNp.name,p.idOFFSET1LIMIT1/*-----------+ | name | id | +-----------+ | Dana | 2  | +-----------*/

In the following example, an error is produced because theOFFSET clause mustcome before theLIMIT clause when they are both used in theRETURN statement:

-- Error: The LIMIT clause must come after the OFFSET clause in a-- RETURN operation.GRAPHFinGraphMATCH(p:Person)RETURNp.name,p.idLIMIT1OFFSET1

In the following example, theORDER BY clause in theRETURN statement sortsthe results byhops and thendestination_account_id:

GRAPHFinGraphMATCH(src:Account{id:7})-[e:Transfers]->{1,3}(dst:Account)RETURNDISTINCTARRAY_LENGTH(e)AShops,dst.idASdestination_account_idORDERBYhops,destination_account_id/*-------------------------------+ | hops | destination_account_id | +-------------------------------+ | 1    | 16                     | | 2    | 20                     | | 3    | 7                      | | 3    | 16                     | +-------------------------------*/

SKIP statement

SKIPcount

Description

Synonym for theOFFSET statement.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

SKIP is a synonym forOFFSET. Therefore, these queries are equivalent:

GRAPHFinGraphMATCH(p:Person)SKIP2RETURNp.name,p.id/*-----------+ | name | id | +-----------+ | Lee  | 3  | +-----------*/
GRAPHFinGraphMATCH(p:Person)OFFSET2RETURNp.name,p.id/*-----------+ | name | id | +-----------+ | Lee  | 3  | +-----------*/

WITH statement

WITH  [ { ALL | DISTINCT } ]return_item[, ... ]  [group_by_clause ]return_item:  {expression [ ASalias ] |* }

Description

Passes on the specified columns, optionally filtering, renaming, andtransforming those results.

Definitions

  • *: Returns all columns in the current working table.
  • ALL: Returns all rows. This is equivalent to not using any prefix.
  • DISTINCT: Returns distinct rows. Deduplication takes place afteraggregations are performed.
  • return_item: A column to include in the results.
  • expression: An expression that represents a column to produce. Aggregationis supported.
  • alias: An alias forexpression.
  • group_by_clause: Groups the current rows of the working table, using theGROUP BY clause.

Details

If any expression performs aggregation, and noGROUP BY clause isspecified, all groupable items from the return list are implicitly used asgrouping keys.

Window functions aren't supported inexpression.

Ordinals aren't supported in theGROUP BY clause.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

The following query returns all distinct destination account IDs:

GRAPHFinGraphMATCH(src:Account)-[transfer:Transfers]->(dst:Account)WITHDISTINCTdstRETURNdst.idASdestination_id/*----------------+ | destination_id | +----------------+ | 7              | | 16             | | 20             | +----------------*/

The following query uses* to carry over the existing columns ofthe working table in addition to defining a new one for the destinationaccount id.

GRAPHFinGraphMATCH(src:Account)-[transfer:Transfers]->(dst:Account)WITH*,dst.idRETURNdst.idASdestination_id/*----------------+ | destination_id | +----------------+ | 7              | | 16             | | 16             | | 16             | | 20             | +----------------*/

In the following example, aggregation is performed implicitly because theWITH statement has an aggregate expression but doesn't specify aGROUP BYclause. All groupable items from the return item list are used as grouping keys.In this case, the grouping keys inferred aresrc.id anddst.id.Therefore, this query returns the number of transfers for eachdistinct combination ofsrc.id anddst.id.

GRAPHFinGraphMATCH(src:Account)-[transfer:Transfers]->(dst:Account)WITHCOUNT(*)AStransfer_total,src.idASsource_id,dst.idASdestination_idRETURNtransfer_total,destination_id,source_id/*---------------------------------------------+ | transfer_total | destination_id | source_id | +---------------------------------------------+ | 2              | 16             | 7         | | 1              | 20             | 16        | | 1              | 7              | 20        | | 1              | 16             | 20        | +---------------------------------------------*/

In the following example, an error is produced because theWITH statement onlycontainsdst.src isn't visible after theWITH statement in theRETURNstatement.

-- Error: src doesn't existGRAPHFinGraphMATCH(src:Account)-[transfer:Transfers]->(dst:Account)WITHdstRETURNsrc.idASsource_id

Set operation

linear_query_statementset_operatorlinear_query_statement[set_operatorlinear_graph_query][...]set_operator:  {     UNION ALL    | UNION DISTINCT    | INTERSECT ALL    | INTERSECT DISTINCT    | EXCEPT ALL    | EXCEPT DISTINCT  }

Description

Combines a sequence of linear query statements with a set operation.Only one type of set operation is allowed per set operation.

Definitions

Details

Each linear query statement in the same set operation shares the same working table.

Most of the rules for GQL set operators are the same as those forSQLset operators, but there are some differences:

  • A GQL set operator doesn't support hints, or theCORRESPONDING keyword.Since each set operation input (a linear query statement) onlyproduces columns with names, the default behavior of GQL set operationsrequires all inputs to have the same set of column names and allpaired columns to share the samesupertype.
  • GQL doesn't allow chaining different kinds of set operations in the sameset operation.
  • GQL doesn't allow using parentheses to separate different set operations.
  • The results produced by the linear query statements are combined in a leftassociative order.

Examples

A set operation between two linear query statements with the same set ofoutput column names and types but with different column orders is supported.For example:

GRAPHFinGraphMATCH(p:Person)RETURNp.name,1ASgroup_idUNIONALLMATCH(p:Person)RETURN2ASgroup_id,p.name/*------+----------+ | name | group_id | +------+----------+ | Alex |    1     | | Dana |    1     | | Lee  |    1     | | Alex |    2     | | Dana |    2     | | Lee  |    2     | +------+----------*/

In a set operation, chaining the same kind of set operation is supported, butchaining different kinds of set operations isn't.For example:

GRAPHFinGraphMATCH(p:Person)RETURNp.name,1ASgroup_idUNIONALLMATCH(p:Person)RETURN2ASgroup_id,p.nameUNIONALLMATCH(p:Person)RETURN3ASgroup_id,p.name/*------+----------+ | name | group_id | +------+----------+ | Alex |    1     | | Dana |    1     | | Lee  |    1     | | Alex |    2     | | Dana |    2     | | Lee  |    2     | | Alex |    3     | | Dana |    3     | | Lee  |    3     | +------+----------*/
-- ERROR: GQL doesn't allow chaining EXCEPT DISTINCT with UNION ALLGRAPHFinGraphMATCH(p:Person)RETURNp.name,1ASgroup_idUNIONALLMATCH(p:Person)RETURN2ASgroup_id,p.nameEXCEPTDISTINCTMATCH(p:Person)RETURN3ASgroup_id,p.name

Graph hints

Note: Syntax characters enclosed in double quotes ("") are literal andrequired.
@"{"hint_key=hint_value "}"

Graph Query Language (GQL) supports hints, which make the query optimizer use aspecific operator in the execution plan. If performance is an issue for you,a GQL hint might be able to help by suggesting a differentquery execution plan shape for your engine. Only one hint key and value areallowed per hint.

Details

You can add the following types of hints to a GQL query:

Hint typeDescription
Join (graph traversal)

Ajoin hint that applies to graph traversal. A graph traversal is semantically equivalent to a join operation between any two tables.

You can use traversal hints in the following ways:

Traversal hints aren't allowed between two subpath patterns or between a subpath pattern and a node pattern.

Join (match statement)

Ajoin hint that applies to aMATCH statement.

Table (graph element)

Atable hint that applies to a graph element. You can use an element hint at the beginning of apattern filler.

Examples

Note: The examples in this section reference a property graph calledFinGraph.

Example of a traversal hint from oneMATCH statement tothe nextMATCH statement:

GRAPHFinGraphMATCH(p:Person{id:1})-[:Owns]->(a:Account)MATCH@{JOIN_METHOD=APPLY_JOIN}(a:Account)-[e:Transfers]->(oa:Account)RETURNoa.id

Example of a traversal hint between twopath patterns:

GRAPHFinGraphMATCH(p:Person{id:1})-[:Owns]->(a:Account),-- path pattern 1@{JOIN_METHOD=HASH_JOIN,HASH_JOIN_BUILD_SIDE=BUILD_RIGHT}-- traversal hint(a:Account)-[e:Transfers]->(c:Account)-- path pattern 2RETURNc.id

Example of a traversal hint from an edge to a node in apath pattern:

GRAPHFinGraphMATCH(p:Person{id:1})-[e:Owns]->@{JOIN_METHOD=APPLY_JOIN}(a:Account)RETURNa.id

Example of a traversal hint from a node to an edge in apath pattern:

GRAPHFinGraphMATCH(p:Person{id:1})@{JOIN_METHOD=APPLY_JOIN}-[e:Owns]->(a:Account)RETURNa.id

Example of a traversal hint between a graph subpath pattern and an edge pattern:

GRAPHFinGraphMATCH(p:Person{id:1})-[e:Owns]->@{JOIN_METHOD=APPLY_JOIN}((a:Account)-[s:Transfers]->(oa:Account))RETURNoa.id

Example of an element hint at the beginning of apattern filler:

GRAPHFinGraphMATCH(a:Account{id:7})-[@{INDEX_STRATEGY=FORCE_INDEX_UNION}:Transfers]-(oa:Account)RETURNoa.id

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.