Updated on 2024-05-23 GMT+08:00

DSL Syntax

Syntax Introduction

The Algorithm query API is a graph DSL provided by GES. You can use it to query and calculate graphs. During service planning, various query operators and fine-grained basic computing pattern operators are added to DSL so that DSL can support user-defined graph traversal, multi-hop filtering query, pattern matching, similarity algorithms, community algorithms, recommendation algorithms, path analysis, and custom service algorithms.

For example, to query the neighborhood vertex set of the second hop from vertices 1 and 2, run the following command:

Match<Vertex> v(['1','2']); v.repeat(bothV()).times(2).limit(3); return v;

DSL Statement Construction

Statements are DSL program fragments that are executed in sequence. To enrich DSL's capability of expressing user-defined algorithms, DSL supports the following statements: selection statement, loop statement, expression statement, operator operand, declaration statement, and jump statement. Typically, the DSL structure consists of a declaration statement, an expression statement, and a jump statement. For example:

GlobalAcc<Sum,int> g=0; // Declaration statement, which declares an aggregator variable g
g+=1*3+2;                // Expression statement, which is used to perform the aggregation operation on the aggregator g. g = g + 1 x 3 + 2
return g;                // Jump statement, which ends DSL and returns g

Currently, only the following selection and loop statements are supported, which are written in selection, loop, and lambda expressions:

  1. Assignment/aggregation of various expressions
  2. Update operator of the Vertex matcher
  3. Gather operator of the Vertex matcher
Table 1 DSL syntax description

Syntax

Keyword

Description

Select statement

if

Executes a statement conditionally.

Loop statement

while

Executes statements repeatedly.

Jump statement

return

Returns different types of results.

Declaration statement

Match< ? >

Declares a matcher Match to quickly match graph data for more operations.

VertexAcc< ?, ?>

Declares a vertex aggregator to define additional properties/variables on a vertex. Match can be used to perform operations on additional variables on vertices in batches.

GlobalAcc< ?, ?>

Declares a global aggregator to define globally operable variables.

Expression statement

operator=

Assigns values to variables.

operator+=

Variable aggregation operation

Arithmetic operations +, -, *, /

Arithmetic operations

Comparison operations >, >=, ==, <, <=, !=

Comparative operations

lambda expression

Anonymous expressions

Operator operation statement

repeat

Allows users to perform multi-hop filtering query. The syntax includes emit, times, and limit.

update

Performs a set of batch operations defined on the matcher

gather

Performs a set of batch operations defined on the matcher

pick

Quickly obtains N random vertices

init

Reinitializes the vertex set of the vertex matcher

insert

Adds a matching vertex set to the vertex matcher

move

Quickly moves the vertex set in other_match_vertex to the match_vertex matcher

subgraph

It is mainly used in the return statement. It can return guidance subgraphs of the match_vertex vertex matcher.

intersection

Takes the intersection of two vertex matchers

pattern

Executes a complete Cypher statement and places the result in the vertex matcher

  1. Select statement: if
    if(expression) {
            true Branching statement
        }

    Executes a statement conditionally.

    GlobalAcc<Sum, int> threshold = 10;   
    Match<Vertex> v(['1', '2']); 
    if(threshold < 20) {
         v.repeat(outV().has('name', 'peter')).times(2).emit();
    }
  2. Loop statement: while
    while(expression) {
            true Branching statement
        }

    Executes some code repeatedly and conditionally

    GlobalAcc<Sum, int> loop = 0;   
    VertexAcc<Sum, int> score = 1;
    Match<Vertex> v(['1', '2']); 
    while(loop < 10) {
         loop +=1;
         v.update((v)->{v.score = 1 + 2 * v.score;});
    }
  3. Jump statement: return

    Returns JSON files of different types and formats

    Type

    Return Type

    Description

    Match

    Vertex set

    -

    VertexAcc

    map

    By default, values that are not changed after initialization are not output.

    GlobalAcc

    Single value

    -

    subgraph

    Vertex set and edge set

    -

    If some vertices are matched, they can be directly returned:

    Match<Vertex> v(['1','2']);
    return v;
    {
        "vertices": [
            {
                "id": "1",
                "label": "movie",
                "properties": {
                    "genres": [
                        "Comedy"
                    ]
                }
            }
            ...
        ]
    }

    Alternatively, ACC values can be directly returned.

    GlobalAcc<Max,int> g1=10; 
    g1+=2;
    return g1;
    {
        "data": {
            "value": 10
        }
    }

    Assume that you want to obtain the guidance subgraph of a match vertex set for subsequent task execution (for example, drawing on the canvas).

    Match<Vertex> v(['1','2']);
    return v.subgraph();
    {
        "data": {
            "vertices": [
                {
                    "id": "1",
                    "label": "user",
                    "properties": {
                        //balabala
                    }
                },
                {
                    "id": "2",
                    "label": "movie",
                    "properties": {
                        //balabala
                    }
                }
            ],
            "edges": [
                {
                    "index": "0",
                    "source": "1",
                    "label": "rate",
                    "properties": {
                        //balabala
                    },
                    "target": "2"
                }
            ]
        }
    }
  4. Expression statement

    An expression is a sequence of operators and operands, which specifies a calculation. Different statements may use expressions. For example, loop statements and selection statements may use expressions to express branches or loop conditions. Expressions can also be used to assign values to variables and perform aggregation operations.

    • The following table lists common operators:

      Common Operator

      Form

      Symbol

      Assignment

      a=b;

      =

      Aggregation

      a+=b

      +=

      Mathmetical

      a+b;a-b;a*b;a/b

      +, -, *, /

      Comparison

      a>b; a=b;a<=b;a==b;a!=b

      >, >=, ==, <, <=, !=

      The calculation of aggregation operations is determined by the definition of Aggregator.

    • The following table lists the priorities among expressions:

      Priority

      Operator

      Combination

      1

      () Function call [] Subscript .Member access a++ Suffix auto-increment a-- Suffix auto-decrement

      Left to right

      2

      a*b a/b Multiplication and division

      Left to right

      3

      a+b a-b Addition and subtraction

      Left to right

      4

      < <= > >= Relational operators

      Left to right

      5

      == != Equality operators

      Left to right

      6

      and Logical AND

      Left to right

      7

      or Logical OR

      Left to right

      8

      = += Assignment, aggregation operations

      Right to left

    • Expression types

      Due to the particularity of variables (different types of aggregators), DSL classifies expressions into the following types:

      1. numeric expression - Numerical expression
      2. vertexacc expression - Expression containing the vertexacc variable
      3. globalacc expression - Expression containing the globalacc variable
      1+2*3 // Numerical expression
      
      GlobalAcc<Sum, int> diff = 0;
      VertexAcc<Sum, int> score = 0;
      Match<Vertex> v(['Tom']);
      
      1+diff*2 // Expression with globalAcc, which belongs to globalacc expression
      1+v.score*2 // Expression with vertexAcc, which belongs to vertexacc expression
    • Expression upgrade table

      There are different constraints on assignment and calculation for different types of expressions. That is, whether the assignment and calculation between different types are valid is restricted.

      The following expressions are used to indicate whether assignment/aggregation operations support different expressions.

      Left Value/Right Value

      Numeric Expression

      VertexAcc Expression

      GlobalAcc Expression

      vertexacc variable

      vertexacc expression

      Partially supported, the same matcher required

      vertexacc expression

      globalacc variable

      globalacc expression

      Not supported

      globalacc expression

    • Value promotion strategy

      During the calculation of an expression, a right value can be converted into a value of another type. The following lists only the supported value promotion strategies:

      1. Integer value promotion: Boolean values can be converted to integer values. The value false changes to 0, and the value true changes to 1.
      2. Floating-point value promotion: Right values of the floating-point type can be converted to values of the double type without changing the values.
    • Value conversion

      Value conversion is currently not supported. Unlike promotion, value conversions can change values and have potential precision losses.

    • Lambda expressions
      ($parameters)->{statements;}

      It is mainly used to receive some steps of a function. For example, both the gather and update steps support transferring lambda expressions as parameters. Variables such as GlobalAcc and VertexAcc are used in lambda expressions to assign and aggregate values. Note the following:

      1. The parameter type does not need to be declared and can be identified in a unified manner.
      2. GlobalAcc in the context can be accessed by lambda expressions.
      3. Lambda expressions can be executed as independent function bodies. The input parameters must be empty.
      GlobalAcc<Sum,int> g1=0;
      g1+=2*10+1;
      ()->{g1+=2*10+1;} // Same result as the previous statement
      
      // update receives lambda as a parameter:
      v.update((v1)->{g1+=v1.acc1*2+g2+v1.acc2;});

Variable Declaration

Match matcher
  1. Match matcher description

    DSL allows you to define objects such as vertices, paths, and submaps that can be matched and on which related operations can be performed. After declaring and initializing the matcher, you can use the matcher operator to perform operations on vertex sets in batches. For details, see Match matcher operators. Run the following statement to declare and initialize the matcher:

    Match<[Vertex|Path|Subgraph]> $variable;

    DSL allows you to define vertices, paths, and submaps that can be matched and on which related operations can be performed.

    Match<Vertex>      Quickly match and perform operations on vertices
  2. Match<Vertex> matcher: Match matcher that can be used to quickly match and perform operations on vertex sets
    Match<[ Vertex ]> $match_vertex_variable; 
    Match<[ Vertex ]> $match_vertex_variable($VertexList);

    You can use Match<Vertex> to match or initialize vertex sets.

    Match<Vertex> v(['1', '2']); // Directly match by vertex ID.
    Match<Vertex> v();          // Only Match variables are defined. The vertices to be matched are empty.
    Match<Vertex> v; 
    v.pattern('match (n:user) where n.age>30 return n limit 10');  // Uses the results of the Cypher statements to match the filtered vertices.

    DSL provides a large number of operators for Match<Vertex>, such as pattern, init, and pick. For details, see Match matcher operators.

  3. Relationship between match matcher and aggregators

    You can define an aggregator to hold values and calculations. Each type of matcher can perform operations on its corresponding aggregator in batches.

    For example, you can use Match<Vertex> to perform aggregation calculation on a specified vertex set.

Aggregator

  1. Aggregator description

    Aggregators are used to simplify the expression of values during calculation. Different types of aggregators define different scopes of batch aggregation operations.

    DSL does not support direct definition of variables of various numeric types to carry data generated during calculation. Instead, DSL provides aggregators to simplify operations in various application scenarios.

    1. VertexAcc can be used to define additional "properties (variables)" on vertices, and Match<Vertex> can be used to perform operations on additional variables on vertices in batches.
    2. GlobalAcc can be used to define globally operable variables.
    Aggregator declaration syntax:
    Accumulator<Aggregator Operator, NumericType> v;
    
    Parameter description:
    NumericType: int, (float and double types are not supported currently)
    Aggregator Operator: Sum,Max,Min

    DSL allows you to define different aggregators to simplify algorithm operations. Currently, two types of aggregate variables are supported:

    1. VertexAcc<Aggregator Operator, type>
    2. GlobalAcc<Aggregator Operator, type>

    You can perform the following operations on an aggregator:

    1. Initialization: Define an aggregator and assign initial values.
    2. Assignment: Reset the aggregator values.
    3. Aggregation: Perform aggregation operations based on defined aggregator operators.
  2. Aggregator operator description

    Different aggregation operations are provided, such as Sum, Max, and Min. Variables are updated using operators + and =.

    $match_vertex.$vertex_accumulator += $value;
    $global_accumulator += $value;
  3. Vertex aggregator VertexAcc<Aggregator Operator, type>

    VertexAcc can be used to quickly define additional "property (variables)" on vertices. and Match<Vertex> can be used to perform operations on additional variables on vertices in batches. This significantly facilitates the calculation process.

    VertexAcc<Sum, float> score = 0.5;

    Each time a VertexAcc is defined, DSL allocates a variable of the type type to each vertex in the full graph. You can use Match<Vertex> to perform operations on the defined VertexAcc. For example:

    VertexAcc<Sum, int> score = 0;
    // Tom.score = 0, Jack.score = 0
    Match<Vertex> v(['Tom', 'Jack']);
    // Tom.score = 0, Jack.score = 0
    v.score += 1; // This operation aggregates the scores of Tom and Jack. That is, their scores are increased by 1.
    // Tom.score = 1, Jack.score = 1
    v.score = 10; //This operation assigns values to the scores of Tom and Jack. That is, their scores are updated to 10.
    // Tom.score = 10, Jack.score = 10
    v.score += 5; // This operation aggregates the scores of Tom and Jack. That is, their scores are increased by 5.
    // Tom.score = 15, Jack.score = 15

    VertexAcc can be operated by expressions. Currently, numeric, GlobalAcc, and VertexAcc expressions can be used for aggregation and assignment.

    VertexAcc<Sum, int> score = 0;
    VertexAcc<Sum, int> factor = 1;
    GlobalAcc<Sum, int> alpha = 10;
    Match<Vertex> v(['Tom']);
    // Tom.score = 0.
    v.score = alpha x 2 + 3; // This operation assigns a value to Tom's score.
    // Tom.score = alpha x 2 + 3 = 10 x 2 + 3 = 23
    
    v.score += v.factor*2; // This operation assigns a value to Jack's score.
    // Tom.score = Tom.score + Tom.factor x 2 = 23 + 1 x 2 = 25
  4. Global aggregator GlobalAcc<Aggregator Operator, type>

    Each time a GlobalAcc is defined, DSL creates a variable of the type type in the DSL scope. Then, perform operations on GlobalAcc directly. For example:

    GlobalAcc<Sum, int> diff = 0;// Define a GlobalAcc.
    diff += 1;// Perform an aggregation operation, that is, diff = Sum (0,1)
    // diff = 1
    diff = 2 x 3;// Assign a value, that is, diff = 2 x 3
    // diff = 6
    GlobalAcc<Sum, int> g2 = 6;// Define a GlobalAcc.
    diff += g2;// Perform an aggregation operation, that is, diff = Sum(6,g2)
    // diff = 12

    GlobalAcc can be operated by expressions. Currently, numeric and GlobalAcc expressions can be used for aggregation and assignment.

    GlobalAcc<Sum, int> alpha = 0;
    GlobalAcc<Sum, int> beta= 10;
    alpha = beta*2+3;
    // alpha = beta x 2 + 3 = 10 x 2 + 3 = 23

Operator Introduction

Match matcher operators

After a Match matcher is defined, different operation operators, such as repeat, gather, update, and pattern, can be used to assist graph calculation and query.

The operation operator varies with the match type.

Operator

Description

Matcher

Anonymous Expression

Select/Loop Statement

repeat

Performs multi-hop filtering like Gremlin.

Vertex

×

×

pick

Randomly selects vertices.

Vertex

×

×

pattern(2.3.11)

Runs Cypher statements.

Vertex

×

×

update

Performs a set of batch operations defined on the matcher.

Vertex

gather

Performs a set of batch operations defined on the matcher.

Vertex

init(2.3.12)

Initializes the matching vertex set based on a specified ID.

Vertex

×

×

insert(2.3.12)

Add new vertices to the matcher.

Vertex

×

×

move(2.3.12)

Quickly moves other matcher vertex sets.

Vertex

×

×

intersection(2.3.12)

Calculates the intersection of vertices.

Vertex

×

×

subgraph(2.3.12)

Obtains guidance subgraphs.

Vertex

×

×

  • repeat

    It allows you to perform multi-hop filtering query. The syntax of repeat is similar to that of repeat in Gremlin. Its semantic expression ability is rich, especially suitable for relational link query.

    For example, if a two-hop query of filtering name=peter is executed from vertex (1,2) to the outgoing direction, it may be expressed in Gremlin as:

    g.V('1','2').repeat(out().has('name','peter')).times(2).emit().dedup()

    In DSL, the preceding functions can be written as follows:

    Match<Vertex> v(['1','2']);
    v.repeat(outV().has('name','peter')).times(2).emit();
    • The repeat step contains some unique associated steps:

      Parameter

      Mandatory

      Type

      Default Value

      Description

      repeat

      Yes

      traversal step

      None

      Executes the repeat rule.

      times

      No

      int

      2

      Maximum number of steps. The default value is 2, and the maximum value is 20.

      emit

      No

      bool

      false

      Whether all elements will be returned. The default value is false. If select-as or path is set for output, this parameter determines whether vertices that are not on the final complete path will be returned.

      limit

      No

      int

      10000

      Number of vertices, edges, or paths.

    • Rules in repeat consist of traversal and filter criteria. They can be multiple rules separated by commas (,).
      Table 2 Traversal process description

      Step

      Description

      outV

      Neighbor vertex in the outgoing direction

      inV

      Neighbor vertex in the ingoing direction

      bothV

      Neighbor vertex in both directions

      outE

      Edge in the outgoing direction

      inE

      Edge in the ingoing direction

      bothE

      Edge in both directions

      otherV

      Neighborhood vertex

      Table 3 Filter criteria description

      Filter Criterion

      Description

      has(key)

      Whether the property name key exists

      has(key, value)

      Whether the value of the property name key is value

      hasLabel(values) (V2.3.5)

      Whether the label value is one of values

      and(filter operator A, filter operator B)

      Logical operator of filter criteria. Criteria A and B must be both met. They can be nested.

      or(filter operator A, filter operator B)

      Logical operator of filter criteria. Either criterion A or B needs to be met. They can be nested.

      and(has('person'), or(has('name', 'peter'), has('age', '30')))
      
      has('person') // The property name person exists.
      has('name', 'peter') // The value of the property name name is peter.
      hasLabel('movie','user') // The label value is movie or user.
      and( has('name', 'peter'), has('age', '30')) // The property name is peter and age is 30.
  • update
    $match_vertex.update($lambda_func);

    The update operator is used to define a group of batch operations on the matcher. Currently, only Match<Vertex> is supported.

    The Update operation on Match<Vertex> applies all operations defined in the input lambda function to the vertices matched by Match.

    The vertex matcher Match<Vertex> receives only lambda expressions that contain one input parameter.

    Match<Vertex> v(['1',2']);
    VertexAcc<Max,int> acc=1; 
    GlobalAcc<Sum,int> g=0;
    v.update( (v1)->{g+=v1.acc*2;} ); //g='1'.acc*2+'2'.acc*2=1*2+1*2=4
    return g; // Return g = 4;
  • gather
    $match_vertex.gather($lambda_func);

    The gather operator is used to define a group of batch operations on the matcher. Currently, only Match<Vertex> is supported.

    • gather of Match<Vertex>

      The Gather operation on Match<Vertex> applies all operations defined in the input lambda function to the edges of the vertices matched by Match.

      The vertex matcher Match receives only lambda expressions that contain two input parameters. The first parameter indicates the source vertex on the edge, and the second parameter indicates the target vertex on the edge.
      Match<Vertex> v(['1',2']);
      VertexAcc<Max,int> acc=1; 
      GlobalAcc<Sum,int> g=0;
      v.gather( (s,t)->{g+=s.acc*2+t.acc;} ); // This operation takes effect on the edges of vertices 1 and 2. That is, 1-2, 1-3, 2-3, 2-1.
      //g=g + 1.acc*2+2.acc + 1.acc*2+3.acc + 2.acc*2+1.acc + 2.acc*2+3.acc
      //g=0 + 3 + 3 + 3 + 3=12
      return g;
  • pick
    $match_vertex.pick(n);

    pick allows you to randomly select N vertices from Match<Vertex>. This function helps you quickly obtain N random vertices.

    Match<Vertex> v();
    v.pick(10); // Select 10 vertices randomly from v.
    return v; // Return information about 10 random vertices.
  • init(2.3.12)
    $match_vertex.init([vertex_list]); // Specify the vertex ID list.
    $match_vertex.init(vertexid); // Specify a single ID.

    Resets the vertex set of the vertex matcher.

    Match<Vertex> v(['1','2']);
    return v;// Return information about vertices 1 and 2.
    Match<Vertex> v(['1','2']);
    v.init(['3','4']);
    return v;// Return information about vertices 3 and 4.
  • insert(2.3.12)
    $match_vertex.insert([vertex_list]); // Specify a list of vertex IDs.
    $match_vertex.insert(vertexid); // Specify a single ID.

    Adds a matching vertex set to the vertex matcher.

    Match<Vertex> v(['1','2']);
    return v;// Return information about vertices 1 and 2.
    
    Match<Vertex> v(['1','2']);
    v.insert(['3','4']);
    return v;// Return information about vertices 1, 2, 3, and 4.
  • move(2.3.12)
    $match_vertex.move(other_match_vertex);

    Quickly moves the vertex set in other_match_vertex to the match_vertex matcher This operator can assign a value to another matcher by one matcher, but does not produce a replication result. Instead, it is similar to the move semantics in C++, that is, moving the original matcher vertex set to the new matcher. After the operation, the original matcher vertex set is cleared.

    Match<Vertex> v1(['1','2']);
    Match<Vertex> v2(['3','4']);
    v1.move(v2);//v1=[3,4],v2=[]
    return v1;// Return information about vertices 3 and 4.
  • subgraph(2.3.12)
    $match_vertex.subgraph();// Return guidance subgraphs of the matcher vertex set.
    $match_vertex.subgraph(filter_step);// Return guidance subgraphs of the matcher vertex set with edge filtering.

    It is mainly used in the return statement. It can return the induced subgraph of the match_vertex vertex matcher.

    When obtaining a subgraph, you can set the filter criterion filter_step on the edge. For details about the syntax, see the filter operator in repeat.

    Match<Vertex> v(['1','2']);
    return v.subgraph();// Return vertices 1 and 2 as well as the edge set between vertices 1 and 2.
    
    Match<Vertex> v(['1','2','3']);
    return v.subgraph(has(year, 2022));// Return vertices 1 and 2 as well as the edge set between vertices 1 and 2.
  • Set basic operations (2.3.12)

    Set operations can be performed on objects in each matcher, such as union and intersection.

    intersection (2.3.12)
    Match<Vertex> start(['1','2']);
    Match<Vertex> target(['2']);
    Match<Vertex> set;
    start.intersection(target);
    return start;// Return vertex 2.
  • Pattern Matching: pattern (2.3.11)

    DSL uses the Cypher syntax to express pattern matching, such as vertex set, path, and subgraph matching.

    Statements that support Cypher:

    Statement

    Supported or Not

    match(2.3.11)

    Partially supported

    limit(2.3.11)

    Supported

    return(2.3.11)

    Supported

    DSL uses the step-pattern of the Match variable to implement pattern matching.

    For example, you need to use a certain rule to match vertices.

    Match<Vertex> v;
    v.pattern('match (n:user) where n.age>30 return n limit 10');

    The pattern is a complete Cypher statement, which filters 10 vertices and returns them to Match<Vertex>.

    String in Cypher

    The pattern syntax contains a complete Cypher statement in single quotation marks. When a string to be expressed, such as an ID or property value, appears in the Cypher statement, double quotation marks are required.

    When using REST APIs to call DSL, you need to add the escape character \ to the double quotation marks. For example:

    Match<Vertex> v;
    v.pattern('match (n) where id(n)=\"12\" return n');
    return v;