An expression is a combination of fixed values, variables, operators, function calls, and groupings which specify a computation, resulting in a data value. This section of the specification describes the literals (fixed values), operators, and functions available in the GSQL query language. It covers the subset of the EBNF definitions shown below. However, more so than in other sections of the specification, syntax alone is not an adequate description. The semantics (functionality) of the particular operators and functions are an essential complement to the syntax.
EBNF for Operations, Functions, and Expressionsconstant := numeric | stringLiteral | TRUE | FALSE | GSQL_UINT_MAX| GSQL_INT_MAX | GSQL_INT_MIN | TO_DATETIME "(" stringLiteral ")"mathOperator := "*" | "/" | "%" | "+" | "-" | "<<" | ">>" | "&" | "|"condition := expr| expr comparisonOperator expr| expr [ NOT ] IN setBagExpr| expr IS [ NOT ] NULL| expr BETWEEN expr AND expr| "(" condition ")"| NOT condition| condition (AND | OR) condition| (TRUE | FALSE)| expr [NOT] LIKE expr [ESCAPE escape_char]comparisonOperator := "<" | "<=" | ">" | ">=" | "==" | "!="aggregator := COUNT | MAX | MIN | AVG | SUMexpr := name| globalAccumName| name ".type"| name "." name| name "." localAccumName ["\'"]| name "." name "." name "(" [argList] ")"| name "." name "(" [argList] ")" [ "." FILTER "(" condition ")" ]| name ["<" type ["," type]* ">"] "(" argList] ")"| name "." localAccumName ("." name "(" [argList] ")")+ ["." name]| globalAccumName ("."name "(" [argList] ")")+ ["."name]| COALESCE "(" [argList] ")"| aggregator "(" [DISTINCT] setBagExpr ")"| ISEMPTY "(" setBagExpr ")"| expr mathOperator expr| "-" expr| "(" expr ")"| "(" argList "->" argList ")" // key value pair for MapAccum| "[" argList "]" // a list| constant| setBagExpr| name "(" argList ")" // function call or a tuple objectsetBagExpr := name| globalAccumName| name "." name| name "." localAccumName| name "." localAccumName ("." name "(" [argList] ")")+| name "." name "(" [argList] ")" [ "." FILTER "(" condition ")" ]| globalAccumName ("." name "(" [argList] ")")+| setBagExpr (UNION | INTERSECT | MINUS) setBagExpr| "(" argList ")"| "(" setBagExpr ")"argList := expr ["," expr]*
constant := numeric | stringLiteral | TRUE | FALSE | GSQL_UINT_MAX| GSQL_INT_MAX | GSQL_INT_MIN | TO_DATETIME "(" stringLiteral ")"
Each primitive data type supports constant values:
Data Type | Constant | Examples |
Numeric types (INT, UINT, FLOAT, DOUBLE) |
| 123 -5 45.67 2.0e-0.5 |
UINT | GSQL_UINT_MAX | |
INT | GSQL_INT_MAX GSQL_INT_MIN | |
boolean | TRUE FALSE | |
string |
|
|
GSL_UINT_MAX = 2 ^ 64 - 1 = 18446744073709551615
GSQL_INT_MAX = 2 ^ 63 - 1 = 9223372036854775807
GSQL_INT_MIN = -2 ^ 63 = -9223372036854775808
An operator is a keyword token which performs a specific computational function to return a resulting value, using the adjacent expressions (its operands) as input values. An operator is similar to a function in that both compute a result from inputs, but syntactically they are different. The most familiar operators are the mathematical operators for addition + and subtraction - .
Tip: The operators listed in this section are designed to behave like the operators in MySQL.
We support the following standard mathematical operators and meanings. The latter four ("<<" | ">>" | "&" | "|") are for bitwise operations. See the section below: "Bit Operators".
mathOperator := "*" | "/" | "%" | "+" | "-" | "<<" | ">>" | "&" | "|"
Operator precedences are shown in the following list, from highest precedence to the lowest. Operators that are shown together on a line have the same precedence:
Operator Precedence, highest to lowest*, /, %-, +<<, >>&|==, >=, >, <=, <, !=
Example 1. Math Operators + - * /CREATE QUERY mathOperators() FOR GRAPH minimalNet api("v2"){int x,y;int z1,z2,z3,z4,z5;float f1,f2,f3,f4;x = 7;y = 3;z1 = x * y; # z = 21z2 = x - y; # z = 4z3 = x + y; # z = 10z4 = x / y; # z = 2z5 = x / 4.0; # z = 1f1 = x / y; # v = 2f2 = x / 4.0; # v = 1.75f3 = x % 3; # v = 1f4 = x % y; # z = 1PRINT x,y;PRINT z1 AS xTIMESy, z2 AS xMINUSy, z3 AS xPLUSy, z4 AS xDIVy, z5 AS xDIV4f;PRINT f1 AS xDIVy, f2 AS xDIV4f, f3 AS xMOD3, f4 AS xMODy;}
mathOperators.json ResultsGSQL > RUN QUERY mathOperators(){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"x": 7,"y": 3},{"xTIMESy": 21,"xPLUSy": 10,"xMINUSy": 4,"xDIVy": 2,"xDIV4f": 1},{"xMODy": 1,"xMOD3": 1,"xDIVy": 2,"xDIV4f": 1.75}]}
We support the standard Boolean operators and standard order of precedence: AND, OR, NOT
Bit operators (<<, >>, &, and |) operate on integers and return an integer.
Bit OperatorsCREATE QUERY bitOperationTest() FOR GRAPH minimalNet{PRINT 80 >> 2; # 20PRINT 80 << 2; # 320PRINT 2 + 80 >> 4; # 5PRINT 2 | 3 ; # 3PRINT 2 & 3 ; # 2PRINT 2 | 3 + 2; # 7PRINT 2 & 3 - 2; # 0}
Operator + can be used for concatenating strings.
The fields of the tuple can be accessed using the dot operator.
A condition is an expression which evaluates to a boolean value of either true or false. One type of condition uses the familiar comparison operators. A comparison operator compares two numeric or string values.
comparisonOperator := "<" | "<=" | ">" | ">=" | "==" | "!="condition := expr| expr comparisonOperator expr| expr [ NOT ] IN setBagExpr| expr IS [ NOT ] NULL| expr BETWEEN expr AND expr| "(" condition ")"| NOT condition| condition (AND | OR) condition| (TRUE | FALSE)| expr [NOT] LIKE expr [ESCAPE escape_char]
Strings are compared based on standard lexicographical ordering: (space) < (digit) < (uppercase_letter) < (lowercase_letter).
The comparison operators treat the STRING COMPRESS type as though it is STRING type.
The expression expr1 BETWEEN expr2 AND expr3 is true if the value expr1 is in the range from expr2 to expr3, including the endpoint values. Each expression must be numeric.
" expr1 BETWEEN expr2 AND expr3 " is equivalent to " expr1 <= expr3 AND expr1 >= expr2".
BETWEEN AND exampleCREATE QUERY mathOperatorBetween() FOR GRAPH minimalNet{int x;bool b;x = 1;b = (x BETWEEN 0 AND 100); PRINT b; # Trueb = (x BETWEEN 1 AND 2); PRINT b; # Trueb = (x BETWEEN 0 AND 1); PRINT b; # True}
IS NULL and IS NOT NULL can be used for checking whether an optional parameter is given any value.
IS NULL exampleCREATE QUERY parameterIsNULL (INT p) FOR GRAPH minimalNet {IF p IS NULL THENPRINT "p is null";ELSEPRINT "p is not null";END;}
parameterIsNULL.json ResultsGSQL > RUN QUERY parameterIsNULL(_){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"p is null": "p is null"}]}GSQL > RUN QUERY parameterIsNULL(3){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"p is not null": "p is not null"}]}
Every attribute value stored in GSQL is a valid value, so IS NULL and IS NOT NULL is only effective for query parameters.
expr [NOT] LIKE expr [ESCAPE escape_char]
The LIKE
operator is used for string pattern matching and can only be used in WHERE
clauses. The expression string1 LIKE string_pattern
evaluates to boolean true if string1
matches the pattern in string_pattern
; otherwise, it is false.
Both operands must be strings. Additionally, while string1
can be a function call (e.g. lower(string_variable)
, string_pattern
must be a string literal or a parameter. A string_pattern
can contain characters as well as the following wildcard and other special symbols, in order to express a pattern (<char_list>
indicates a placeholder):
Character or syntax | Description | Example |
| matches zero or more characters. |
|
| matches any single character. |
|
| matches any character in a char list. A char list is a concatenated character set, with no separators. |
|
| matches any character NOT in a char list. |
|
| matches any character NOT in a char list. | |
| (Special syntax within a char list) matches a character in the range from α to β. A char list can have multiple ranges. |
|
| (Special syntax within a char list) matches the character | |
| (Special syntax within a char list) matches the character |
|
The optional ESCAPE escape_char
clause is used to define an escape character. When escape_char
occurs in string_pattern
, then the next character is interpreted literally, instead of as a pattern matching operator. For example, if we want to specify the pattern "any string ending with the '%'
character", we could use
"%\%" ESCAPE "\"
The first "%"
has its usual pattern-matching meaning "zero or more characters".
"\%"
means a literal percentage character, because it starts with the escape character "\"
.
There are a number of built-in functions which act on either an accumulator, a base type, or vertex variable. The accumulator function calls are discussed in detail in the "Accumulators" section.
Below is a list of built-in functions which act on either INT, FLOAT, or DOUBLE value(s).
Function name and parameters | Description | Return type |
abs (NUM num ) | Returns the absolute value of num | Same as parameter type |
sqrt ( NUM num ) | Returns the square root of num | FLOAT |
pow ( NUM base , NUM exp ) | Returns base exp | If base and exp are both INT → INT; Otherwise → FLOAT |
acos ( NUM num ) | arc cosine | FLOAT |
asin ( NUM num ) | arc sine | FLOAT |
atan ( NUM num ) | arc tangent | FLOAT |
atan2 (NUM y , NUM x ) | arc tangent of y / x | FLOAT |
ceil ( NUM num ) | rounds upward | INT |
cos ( NUM num ) | cosine | FLOAT |
cosh ( NUM num ) | hyperbolic cosine | FLOAT |
exp ( NUM num ) | base-e exponential | FLOAT |
floor ( NUM num ) | rounds downward | INT |
fmod (NUM numer , NUM denom ) | floating-point remainder of numer / denom | FLOAT |
ldexp (NUM x , NUM exp ) | Returns x multiplied by 2 raised to the power of exp.
| FLOAT |
log ( NUM num ) | natural logarithm | FLOAT |
log10 ( NUM num ) | common (base-10) logarithm | FLOAT |
sin ( NUM num ) | sine | FLOAT |
sinh ( NUM num ) | hyperbolic sine | FLOAT |
tan ( NUM num ) | tangent | FLOAT |
tanh ( NUM num ) | hyperbolic tangent | FLOAT |
to_string (NUM num ) | Converts num to a STRING value | STRING |
float_to_int (FLOAT num ) | Converts num to a INT value by truncating the floating part | INT |
str_to_int (STRING str ) | Converts str to a INT value. If str is a floating number, the floating part is truncated; If str is not a numerical value, returns 0. | INT |
function name and parameters | description | return type |
to_string (NUM num) | Converts num to a STRING | STRING |
float_to_int (FLOAT num) | Converts num to a INT value by truncating the floating point | INT |
str_to_int (STRING str) | Concerts str to a INT value. If str is a floating number, the floating part is truncated. If str is not a numerical value, returns 0. | INT |
The following built-in functions are provided for text processing. Note that these functions do not modify the input parameter. They each return a new string.
function name and parameters | description | return type |
lower(STRING str ) | Converts str to all lowercase letters | STRING |
upper(STRING str ) | Converts str to all uppercase letters | STRING |
trim( [ [ LEADING | TRAILING | BOTH ] [STRING removal_char ] FROM ] STRING str ) | Trims* characters from the leading and/or trailing ends of str | STRING |
In the syntax for trim(), the words in bold ( LEADING, TRAILING, BOTH, and FROM ) are keywords which should appear exactly as shown.
STRING is just an indicator of the datatype; it is not an explicit keyword.
The trim() function have the following options:
By using one of the keywords LEADING, TRAILING, or BOTH, the user can specify that characters are to be removed from the left end, right end, or both ends of the string, respectively. If none of these keywords is used, the function will removed from both ends.
removal_char is a single character. The function will remove consecutive instances of removal_char , until it encounters a different character. If removal_char is not specified, then trim() removes whitespace (spaces, tabs, and newlines).
CREATE QUERY stringFuncEx() FOR GRAPH minimalNet {#Example stringsstring a = " Abc ";string b = "aa ABC aaa";string c = " a A ";PRINT lower(a); # prints " abc "PRINT upper(b); # prints "AA ABCC AAA"PRINT trim(a); # prints "Abc"PRINT trim(BOTH a); # prints "Abc"PRINT trim(LEADING c); # prints "a A "PRINT trim(TRAILING "a" FROM b); # prints "aa ABC "#You can combine functions for more convenient calling:PRINT trim(BOTH trim(BOTH " " FROM c) FROM b);# prints "BC"}
Notes about the trim() function:
The following functions convert from/to DATETIME to/from other types.
function name and parameters | description | return type |
to_datetime (STRING str ) | Converts str to a DATETIME value | DATETIME |
epoch_to_datetime (INT int_value ) | Converts int_value to a DATETIME value by epoch time conversion | DATETIME |
datetime_to_epoch (DATETIME date ) | Converts date to epoch time. | INT |
The following function converts a DATETIME value into a string format specified by the user:
function name and parameters | description | return type |
datetime_format( DATETIME date[, STRING str ] ) | Prints date as the str indicates. The following specifiers may be used as the format of str . The “%” character is required before the format specifier characters. If str is not given, "%Y-%m-%d %H:%M:%S" is used. Specifier:
| STRING |
datetime_format example# Show all posts's post timeCREATE QUERY allPostTime() FOR GRAPH socialNet api("v2") {start = {post.*};#PRINT datetime_format(start.postTime, "a message was posted at %H:%M:%S on %Y/%m/%d");PRINT start[datetime_format(start.postTime, "a message was posted at %H:%M:%S on %Y/%m/%d") as postTimeMsg]; // api v2}
The followings are other functions related to DATETIME :
function name and parameters | description | return type |
now() | Returns the current time in DATETIME type. | DATETIME |
year( DATETIME date ) | Extracts the year of date . | INT |
month( DATETIME date ) | Extracts the month of date. | INT |
day( DATETIME date ) | Extracts the day of month of date . | INT |
hour( DATETIME date ) | Extracts the hour of date . | INT |
minute( DATETIME date ) | Extracts the minute of date . | INT |
second( DATETIME date ) | Extracts the second of date . | INT |
datetime_add( DATETIME date, INTERVAL int_value time_unit) | INTERVAL is a keyword; time_unit is one of the keywords YEAR, MONTH, DAY, HOUR, MINUTE, or SECOND. The function returns the DATETIME value which is int_value units later than date. For example, datetime_add( now(), INTERVAL 1 MONTH ) returns a DATETIME value which is 1 month from now. | DATETIME |
datetime_sub( DATETIME date, INTERVAL int_value time_unit ) | Same as datetime_add, except that the returned value is int_value units earlier than date . | DATETIME |
datetime_diff( DATETIMEdate1 , DATETIME date2) | Returns the difference in seconds of these two DATETIME values: ( date1 - date2 ) . | INT |
JSONOBJECT and JSONARRAY are base types, meaning they can be used as a parameter type, an element type for most accumulators, or a return type. This enables the input and output of complex, customized data structures. For input and output, a string representation of the JSON is used. Hence, the GSQL query language offers several functions to convert a formatted string into JSON and then to search and access the components of a JSON structure.
Data Conversion Functions
The following parsing functions convert a string into a JSONOBJECT or a JSONARRAY:
function name | description | return type |
parse_json_object(STRING str ) | Converts str into a JSON object | JSONOBJECT |
parse_json_array( STRING str ) | Converts str into a JSON array | JSONARRAY |
Both functions generate a run-time error if the input string cannot be converted into a JSON object or a JSON array. To be properly formatted, besides having the proper nesting and matching of curly braces { } and brackets [ ], each value field must be one of the following: a string (in double quotes "), a number, a boolean ( true or false ), or a JSONOBJECT or JSONARRAY. Each key of a key:value pair must be a string in double quotes.
See examples below.
parse_json_object and parse_json_array exampleCREATE QUERY jsonEx (STRING strA, STRING strB) FOR GRAPH minimalNet {JSONARRAY jsonA;JSONOBJECT jsonO;jsonA = parse_json_array( strA );jsonO = parse_json_object( strB );PRINT jsonA, jsonO;}
jsonEx.json ResultGSQL > RUN QUERY jsonEx("[123]","{\"abc\":123}")or curl -X GET 'http://localhost:9000/query/jsonEx?strA=\[123\]&strB=\{"abc":123\}'{"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"jsonA": [123],"jsonO": {"abc": 123}}]}GSQL > RUN QUERY jsonEx("{123}","{\"123\":\"123\"}")Runtime Error: {123} cannot be parsed as a json array.
Data Access Methods
JSONOBJECT and JSONARRAY are object classes, each class supporting a set of data access methods, using dot notation:
jsonVariable.functionName(parameter_list)
The following methods (class functions) can act on a JSONOBJECT variable:
method name | description | return type |
containsKey(STRING keyStr ) | Returns a boolean value indicating whether the JSON object contains the key keyStr . | BOOL |
getInt(STRING keyStr ) | Returns the numeric value associated with key keyStr as an INT. | INT |
getDouble (STRING keyS tr ) | Returns the numeric value associated with key keyStr as a DOUBLE. | DOUBLE |
getString (STRING keyS tr ) | Returns the string value associated with key keyStr . | STRING |
getBool (STRING keyS tr ) | Returns the bool value associated with key keyStr . | BOOL |
getJsonObject (STRING keyS tr ) | Returns the JSONOBJECT associated with key keyStr . | JSONOBJECT |
getJsonArray (STRING keySt r ) | Returns the JSONARRAY associated with key keyStr . | JSONARRAY |
The above getType(STRING keyStr ) function generates a run-time error if
The key keyStr doesn't exist, or
The function's return type is different than the stored value type. See the next note about numeric data.
Pure JSON stores "numbers" without distinguishing between INT and DOUBLE, but for TigerGraph, if the input value is all digits, it will be stored as INT. Other numeric values are stored as DOUBLE. The getDouble function can read an INT and return its equivalent DOUBLE value, but it is an error to call getINT for a DOUBLE value.
The following methods can act on a JSONARRAY variable:
method name | description | return type |
size() | Returns the size of this array. | INT |
getInt( INT idx ) | Returns the numeric value at position idx as an INT. | INT |
getDouble( INT idx ) | Returns the numeric value at position idx as a DOUBLE. | DOUBLE |
getString( INT idx ) | Returns the string value at position idx . | STRING |
getBool( INT idx ) | Returns the bool value at position idx . | BOOL |
getJsonObject( INT idx ) | Returns the JSONOBJECT value at position idx . | JSONOBJECT |
getJsonArray( INT idx ) | Returns the JSONARRAY value at position idx . | JSONARRAY |
Similar to the methods of JSONOBJECT, the above getType(INT idx ) function generates a run-time error if
idx is out of bounds, or
The function's return type is different than the stored value type. See the next note about numeric data.
Pure JSON stores "numbers" without distinguishing between INT and DOUBLE, but for TigerGraph, if the input value is all digits, it will be stored as INT. Other numeric values are stored as DOUBLE. The getDouble function can read an INT and return its equivalent DOUBLE value, but it is an error to call getINT for a DOUBLE value.
Below is an example of using these functions and methods :
JSONOBJECT and JSONARRAY function exampleCREATE QUERY jsonEx2 () FOR GRAPH minimalNet {JSONOBJECT jsonO, jsonO2;JSONARRAY jsonA, jsonA2;STRING str, str2;str = "{\"int\":1, \"double\":3.0, \"string\":\"xyz\", \"bool\":true, \"obj\":{\"obj\":{\"bool\":false}}, \"arr\":[\"xyz\",123,true] }";str2 = "[\"xyz\", 123, false, 5.0]";jsonO = parse_json_object( str ) ;jsonA = parse_json_array( str2 ) ;jsonO2 = jsonO.getJsonObject("obj");jsonA2 = jsonO.getJsonArray("arr");PRINT jsonO;PRINT jsonO.getBool("bool"), jsonO.getJsonObject("obj"), jsonO.getJsonArray("arr"), jsonO2.getJsonObject("obj"), jsonA2.getString(0) , jsonA.getDouble(3), jsonA.getDouble(1);}
jsonEx2.json ResultGSQL > RUN QUERY jsonEx2(){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [ {"jsonO": { "arr": [ "xyz", 123, true ],"bool": true,"string": "xyz","double": 3,"obj": {"obj": {"bool": false}},"int": 1}},{"jsonO.getBool(bool)": true,"jsonA.getDouble(3)": 5,"jsonA.getDouble(1)": 123,"jsonO.getJsonObject(obj)": {"obj": {"bool": false}},"jsonO2.getJsonObject(obj)": {"bool": false},"jsonO.getJsonArray(arr)": [ "xyz", 123, true ],"jsonA2.getString(0)": "xyz"}]}
Attributes on vertices or edges are defined in the graph schema. Additionally, each vertex and edge has a built-in STRING attribute called type which represents the user-defined type of that edge or vertex. These attributes, including type, can be accessed for a particular edge or vertex with the dot operator:
Accessing attributes with a known name.name ".type" // read only. Returns vertexType or edgeType of namename "." attrName // read/write. Accesses attribute called attrName
DYNAMIC Query Support
The name of the attribute can be parameterized using the getAttr and setAttr vertex functions, described later in this section. This allows you to write dynamic query procedures where the attribute names are specified when you run the query.
For example, the following code snippet shows two different SELECT statements which produce equivalent results. The first uses the dot operator on the vertex variable v to access the "subject" attribute, which is defined in the graph schema. The FROM clause in the first SELECT statement necessitates that any target vertices will be of type "post" (also defined in the graph schema). The second SELECT schema checks that the vertex variable v's type is a "post" vertex by using the dot operator to access the built-in type attribute.
Accessing vertex variable attributesCREATE QUERY coffeeRelatedPosts() FOR GRAPH socialNet{allVertices = {ANY};results = SELECT v FROM allVertices:s -(:e)-> post:v WHERE v.subject == "coffee";PRINT results;results = SELECT v FROM allVertices:s -(:e)-> :v WHERE v.type == "post" AND v.subject == "coffee";PRINT results;}
Results for Query coffeeRelatedPostsGSQL > RUN QUERY coffeeRelatedPosts(){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"results": [{"v_id": "4","attributes": {"postTime": "2011-02-07 05:02:51","subject": "coffee"},"v_type": "post"}]},{"results": [{"v_id": "4","attributes": {"postTime": "2011-02-07 05:02:51","subject": "coffee"},"v_type": "post"}]}]}
Below is a list of built-in functions that can be accessed by vertex aliases, using the dot operator:
Syntax for vertex functionsvertex_alias.function_name(argList)[.FILTER(condition)]
Currently, these functions are only available for vertex aliases (defined in the FROM clause); vertex variables do not have these functions.
Note that in order to calculate outdegree by edge type, the graph schema must be defined such that vertices keep track of their edge types using WITH STATS="OUTDEGREE_BY_EDGETYPE" (however, "OUTDEGREE_BY_EDGETYPE" is now the default STATS option).
Function | Description | Return type |
outdegree ([STRING edgeType ]) | Returns the recent number* [see note below] of outgoing or undirected edges connected to the vertex. If the optional argument edgeType is given, then count only edges of the given edgeType. | INT |
neighbors ([ STRING edgeType ]) | Returns the set of ids for the vertices which are out-neighbors or undirected neighbors of the vertex. If the optional argument edgeType is given, then include only those neighbors reachable by edges of the given edgeType. | BagAccum<VERTEX> |
neighborAttribute ( STRING edgeType, STRING targetVertexType, STRING attrName) | From the given vertex, traverses the given edgeType to the given targetVertexType , and returns the set of values for the vertex attribute called attrName. edgeType can only be string literal. | BagAccum<attrType> |
edgeAttribute ( STRING edgeType, STRING attrName) | From the given vertex, traverses the given edgeType, and returns the set of values for the edge attributed called attrName. edgeType can only be string literal. | BagAccum<attrType> |
getAttr (STRING attrName, STRING attrType) | Returns the value of the attribute called attrName of type attrType. attrType can "INT", "UINT", "FLOAT", "DOUBLE", "BOOL", "STRING", or "DATETIME". | attrType |
setAttr (STRING attrName, attrType newValue) | Sets the value of the attribute called attrName to newValue. | n/a |
Note on outdegree(): This function reads a metadata value stored with each vertex, to avoid traversing the graph and thus have a fast response. The snapshot transaction semantics means that outdegree() may sometimes read an old value if there are concurrent write transactions. To guarantee an accurate count, traverse the neighboring edges and count them with a SumAccum, or use a function like neighbors() and then use size() on the set.
Vertex function examplesCREATE QUERY vertexFunctionExample(vertex<person> m1) FOR GRAPH socialNet {SetAccum<Vertex> @neighborSet;SetAccum<Vertex> @neighborSet2;SetAccum<DATETIME> @attr1;BagAccum<DATETIME> @attr2;int deg1, deg2, deg3, deg4;S = {m1};S2 = SELECT SFROM S - (posted:e) -> post:tACCUM deg1 = S.outdegree(),deg2 = S.outdegree("posted"),deg3 = S.outdegree(e.type), # same as deg2STRING str = "posted",deg4 = S.outdegree(str); # same as deg2PRINT deg1, deg2, deg3, deg4;S3 = SELECT SFROM S:sPOST-ACCUM s.@neighborSet += s.neighbors(),s.@neighborSet2 += s.neighbors("posted"),s.@attr1 += s.neighborAttribute("posted", "post", "postTime"),s.@attr2 += s.edgeAttribute("liked", "actionTime");PRINT S3;}
vertexFunctionExample ResultGSQL > RUN QUERY vertexFunctionExample("person5"){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"deg4": 2,"deg2": 2,"deg3": 2,"deg1": 5},{"S3": [{"v_id": "person5","attributes": {"@attr2": [1263330725],"@attr1": [1297054971,1296694941],"gender": "Female","@neighborSet": ["6","11","4","person7","person4"],"id": "person5","@neighborSet2": ["4","11"]},"v_type": "person"}]}]}
The optional .FILTER(condition) clause offers an additional filter for selecting which elements are added to the output set of the neighbor, neighborAttribute and edgeAttribute functions. The condition is evaluated for each element . If the condition is true, the element is added to the output set; if false, it is not. An example is shown below:
Example: vertex functions with optional filterCREATE QUERY filterEx (SET<STRING> pIds, INT yr) FOR GRAPH workNet api("v2") {SetAccum<vertex<company>> @recentEmplr, @allEmplr;BagAccum<string> @diffCountry, @allCountry;Start = {person.*};L0 = SELECT vFROM Start:vWHERE v.id IN pIdsACCUM# filter using edge attributev.@recentEmplr += v.neighbors("worksFor").filter(worksFor.startYear >= yr),v.@allEmplr += v.neighbors("worksFor").filter(true),# vertex alias attribute and neighbor type attributev.@diffCountry += v.neighborAttribute("worksFor", "company", "id").filter(v.locationId != company.country),v.@allCountry += v.neighborAttribute("worksFor", "company", "id");PRINT yr, L0[L0.@recentEmplr, L0.@allEmplr, L0.@diffCountry, L0.@allCountry]; // api v2}
Results in filterEx.jsonGSQL > RUN QUERY filterEx(["person1","person2"],2016){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"L0": [{"v_id": "person1","attributes": {"[email protected]": ["company2"],"[email protected]": ["company1"],"[email protected]": [ "company1", "company2" ],"[email protected]": [ "company2", "company1" ]},"v_type": "person"},{"v_id": "person2","attributes": {"[email protected]": ["company1"],"[email protected]": [],"[email protected]": [ "company1", "company2" ],"[email protected]": [ "company2", "company1" ]},"v_type": "person"}],"yr": 2016}]}
Below are the built-in functions that can be accessed by edge aliases, using the dot operator. Edge functions follow the same general rules as vertex functions (see above).
function name | description | return type |
isDirected() | Returns a boolean value indicating whether this edge is directed or undirected. | BOOL |
getAttr (STRING attrName, STRING attrType) | Returns the value of the attribute called attrName of type attrType. attrType can "INT", "UINT", "FLOAT", "DOUBLE", "BOOL", "STRING", or "DATETIME". | attrType |
setAttr (STRING attrName, attrType newValue) | Sets the value of the attribute called attrName to newValue. | n/a |
This section describes functions which apply to all or most accumulators. Other accumulator functions for each accumulator type are illustrated at the "Accumulator Type" section.
The tick operator ( ' ) can be used to read the value of an accumulator as it was at the start an ACCUM clause, before any changes that took place within the ACCUM clause. It can only be used in the POST-ACCUM clause. A typical use is to compare the value of the accumulator before and after the ACCUM clause. The PageRank algorithm provides a good example:
v = SELECT sFROM start:s - (e_type:e) -> :tACCUM t.@received_score += s.@score/(s.outdegree(e_type))POST-ACCUM s.@score = (1.0 - damping) + damping * s.@received_score,s.@received_score = 0,@@max_diff += abs(s.@score - s.@score');
In the last line, we compute @@max_diff
as the absolute value of the difference between the post-ACCUM score ([email protected]
) and the pre-ACCUM score ([email protected]'
).
SELECT blocks take an input vertex set and perform various selection and filtering operations to produce an output set. Therefore, set/bag expressions and their operators are a useful and powerful part of the GSQL query language. A set/bag expression can use either SetAccum or BagAccum.
EBNFsetBagExpr := name| globalAccumName| name "." name| name "." localAccumName| name "." localAccumName ("." name "(" [argList] ")")+| name "." name "(" [argList] ")" [ "." FILTER "(" condition ")" ]| globalAccumName ("." name "(" [argList] ")")+| setBagExpr (UNION | INTERSECT | MINUS) setBagExpr| "(" argList ")"| "(" setBagExpr ")"
The operators are straightforward, when two operands are both sets, the result expression is a set. When at least one operant is a bag, the result expression is a bag. If one operant is a bag and the other is a set, the operator treats the set operant as a bag containing one of each value.
Set/Bag Operator Examples# Demonstrate Set & Bag operatorsCREATE QUERY setOperatorsEx() FOR GRAPH minimalNet {SetAccum<INT> @@setA, @@setB, @@AunionB, @@AintsctB, @@AminusB;BagAccum<INT> @@bagD, @@bagE, @@DunionE, @@DintsctE, @@DminusE;BagAccum<INT> @@DminusA, @@DunionA, @@AunionBbag;BOOL x;@@setA = (1,2,3,4); PRINT @@setA;@@setB = (2,4,6,8); PRINT @@setB;@@AunionB = @@setA UNION @@setB ; PRINT @@AunionB; // (1, 2, 3, 4, 6, 8)@@AintsctB = @@setA INTERSECT @@setB; PRINT @@AintsctB; // (2, 4)@@AminusB = @@setA MINUS @@setB ; PRINT @@AminusB; // C = (1, 3)@@bagD = (1,2,2,3); PRINT @@bagD;@@bagE = (2,3,5,7); PRINT @@bagE;@@DunionE = @@bagD UNION @@bagE; PRINT @@DunionE; // (1, 2, 2, 2, 3, 3, 5, 7)@@DintsctE = @@bagD INTERSECT @@bagE; PRINT @@DintsctE; // (2, 3)@@DminusE = @@bagD MINUS @@bagE; PRINT @@DminusE; // (1, 2)@@DminusA = @@bagD MINUS @@setA; PRINT @@DminusA; // (2)@@DunionA = @@bagD UNION @@setA; PRINT @@DunionA; // (1, 1, 2, 2, 2, 3, 3, 4)// because bag UNION set is a bag@@AunionBbag = @@setA UNION @@setB; PRINT @@AunionBbag; // (1, 2, 3, 4, 6, 8)// because set UNION set is a set}
setOperatorsEx Query ResultsGSQL > RUN QUERY setOperatorsEx(){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [ {"@@setA": [ 4, 3, 2, 1 ]},{"@@setB": [ 8, 6, 4, 2 ]},{"@@AunionB": [ 4, 3, 2, 1, 8, 6 ]},{"@@AintsctB": [ 4, 2 ]},{"@@AminusB": [ 3, 1 ]},{"@@bagD": [ 1, 2, 2, 3 ]},{"@@bagE": [ 2, 7, 3, 5 ]},{"@@DunionE": [ 1, 2, 2, 2, 3, 3, 7, 5 ]},{"@@DintsctE": [ 2, 3 ]},{"@@DminusE": [ 1, 2 ]},{"@@DminusA": [2]},{"@@DunionA": [ 1, 1, 2, 2, 2, 3, 3, 4 ]},{"@@AunionBbag": [ 6, 8, 1, 2, 3, 4 ]}]}
The result of these operators is another set or bag, so these operations can be nested and chained to form more complex expressions, such as
(setBagExpr_A INTERSECT (setBagExpr_B UNION setBagExpr_C) ) MINUS setBagExpr_D
For example , suppose setBagExpr_A is ("a", "b", "c")
"a" IN setBagExpr_A => true"d" IN setBagExpr_A => false"a" NOT IN setBagExpr_A => false"d" NOT IN setBagExpr_A => true
The IN and NOT IN operators support all base types on the left-hand side, and any set/bag expression on the right-hand side. The base type must be the same as the accumulator's element type. IN and NOT IN return a BOOL value.
The following example uses NOT IN to exclude neighbors that are on a blocked list.
Set Membership exampleCREATE QUERY friendsNotInblockedlist (VERTEX<person> seed, SET<VERTEX<person>> blockedList) FOR GRAPH socialNet `{Start = {seed};Result = SELECT vFROM Start:s-(friend:e)-person:vWHERE v NOT IN blockedList;PRINT Result;}
Results for Query friendsNotInblockedlistGSQL > RUN QUERY friendsNotInblockedlist("person1", ["person2"]){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"Result": [{"v_id": "person8","attributes": {"gender": "Male","id": "person8"},"v_type": "person"}]}]}
Aggregation function syntaxaggregator "(" [DISTINCT] setBagExpr ")"aggregator := COUNT | MAX | MIN | AVG | SUM
The aggregation functions take a set/bag expression as its input parameter and return one value or element.
Beginning in v3.1, the DISTINCT
keyword can be used to only include distinct values when aggregating. That is, if the same value appears more than once, include the value only once.
count() : Returns the size (INT) of the set.
sum() : Returns the sum of all elements. This is only applicable to a set/bag expression with numeric type.
min() : Returns the member with minimum value. This is only applicable to a set/bag expression with numeric type.
max() : Returns the member with maximum value. This is only applicable to a set/bag expression with numeric type.
avg() : Returns the average of all elements. This is only applicable to a set/bag expression with numeric type. The average is INT if the element type of the set/bag expression is INT.
Aggregation function exampleCREATE QUERY aggregateFuncEx(BAG<INT> x) FOR GRAPH minimalNet {BagAccum<INT> @@t;@@t += -5; @@t += 2; @@t+= -1;PRINT max(@@t), min(@@t), avg(@@t), count(@@t), sum(@@t);PRINT max(x), min(x), avg(x), count(x), sum(x);}
aggregateFuncEx.json ResultGSQL > RUN QUERY aggregateFuncEx([1,2,5]){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"sum(@@t)": -4,"count(@@t)": 3,"max(@@t)": 2,"avg(@@t)": -1,"min(@@t)": -5},{"avg(x)": 2,"count(x)": 3,"max(x)": 5,"min(x)": 1,"sum(x)": 8}]}
SelectVertex() reads a data file which lists particular vertices of the graph and returns the corresponding vertex set. This function can only be used in a vertex set variable declaration statement as a seed set. The data file must be organized as a table with one or more columns. One column must be for vertex id. Optionally, another column is for vertex type. SelectVertex() has five parameters explained in the below table: filePath, vertexIdColumn, vertexTypeColumn, separator, and header. The rules for column separators and column headings are the same as for the GSQL Loader.
parameter name | type | description |
filePath | string | The absolute file path of the input file to be read. A relative path is not supported. |
vertexIdColumn | $ num , or $ "column_name" if header is true. | The vertex id column position. |
vertexTypeColumn | $ num , $ "column_name" if header is true, or a vertex type | The vertex type column position or a specific vertex type. |
separator | single-character string | The column separator character. |
header | bool | Whether this file has a header. |
One vertex set variable declaration statement can have multiple SelectVertex() function calls. However, if a declaration statement has multiple SelectVertex() calls referring to the same file, they must use the same separator and header parameters. If any row of the file contains an invalid vertex type, a run time error occurs; if any row of the file contains an nonexistent vertex id, a warning message is shown with the count of nonexistent ids.
Below is a query example using SelectVertex calls, reading from the data file selectVertexInput.csv.
selectVertexInput.csvc1,c2,c3person1,person,3person5,person,4person6,person,5
selectVertex exampleCREATE QUERY selectVertexEx(STRING filename) FOR GRAPH socialNet {S = {SelectVertex(filename, $"c1", $1, ",", true),SelectVertex(filename, $2, post, ",", true)};PRINT S;}
ResultGSQL > RUN QUERY selectVertexEx("/file_directory/selectVertexInput.csv"){"error": false,"message": "","version": {"edition": "developer","schema": 0,"api": "v2"},"results": [{"S": [{"v_id": "4","attributes": {"postTime": "2011-02-07 05:02:51","subject": "coffee"},"v_type": "post"},{"v_id": "person1","attributes": {"gender": "Male","id": "person1"},"v_type": "person"},{"v_id": "person5","attributes": {"gender": "Female","id": "person5"},"v_type": "person"},{"v_id": "3","attributes": {"postTime": "2011-02-05 01:02:44","subject": "cats"},"v_type": "post"},{"v_id": "5","attributes": {"postTime": "2011-02-06 01:02:02","subject": "tigergraph"},"v_type": "post"},{"v_id": "person6","attributes": {"gender": "Male","id": "person6"},"v_type": "person"}]}]}
to_vertex() and to_vertex_set() convert a string or a string set into a vertex or a vertex set, respectively, of a given vertex type. These two functions are useful when the vertex id(s) are obtained and only known at run-time.
Running these functions requires real-time conversion of an external id to a GSQL internal id, which is a relatively slow process. Therefore,
If the user can always know the id before running the query, define the query with VERTEX or SET<VERTEX> parameters instead of STRING or SET<STRING> parameters, and avoid calling to_vertex() or to_vertex_set().
Calling to_vertex_set() one time is much faster than c alling to_vertex() multiple times . Use to_vertex_set() instead of to_vertex() as much as possible.
The first parameter of to_vertex() is the vertex id string. The first parameter of to_vertex_set() is a string set representing vertex ids. The second parameter of both functions is the vertex type string.
Function signatures for to_vertex() and to_vertex_set()VERTEX to_vertex(STRING id, STRING vertex_type