A-B query and K-Hop query use edge_filter()
and node_filter()
to filter the edges and intermediate nodes in paths, that is to say, the edges must meet the same filtering rules, so do the intermediate nodes. If different rules are required to filter edges or intermediate nodes, template query is needed.
Basic templates describe the filtering rules the minimum unit (node, edge) in the path has to meet. Multiple basic templates assembled into path or subgraph can make structural matching in the graph to accommodate the business needs with celerity and great customizability.
Ultipa currently supports the following 4 basic templates:
Basic Template | Type | Description | Structure of Custom Alias |
---|---|---|---|
n() |
Single node | The filtering rules of one node in the path |
NODE |
e() , e()[1] ,le() , le()[1] , re() , re()[1] |
Single edge | The filtering rules of one edge in the path; edge direction is none, left or right (the same below) |
EDGE |
e()[<steps>] ,le()[<steps>] ,re()[<steps>] |
Multi-edge | The filtering rules of multiple consecutive edges in the path format of [<steps>] (N ≥ 2): [N] : N edges [:N] : 1~N edges [0:N] : 0~N edges (see note below) [M:N] : M~N edges [*:N] : the shortest paths within N edges |
Custom alias not supported |
e().nf()[<steps>] ,le().nf()[<steps>] ,re().nf()[<steps>] |
Multi-edge with Nodes | The filtering rules of multiple consecutive edges and nodes between those edges in the path format of [<steps>] is the same as above |
Custom alias not supported |
Note: when setting [0:N] as length of a multi-edge template, for each start node of this edge template, if paths are found with 1~N edges of this particular edge template, then return these paths; if no such path is found and the start node and end node of this edge template (the node templates before and after this edge template) have the same filtering condition, then the edge template and the node template after it are discarded, in which case the result of 0 step is returned.
Assembling Rules
- Rule No.1: A path starts and ends with node, and consists of alternating nodes and edges.
For instance, a path of 4-node-3-edge should be n().e().n().e().n().e().n(). One can easily set independent filters and alias for each node or edge in the path.
n({@product}).le({@view}).n({@customer} as n1)
.re({@has}).n({@card} as n2)
.re({@transfer} as e1).n({@card}) as p
return p{*}, n1{*}, n2{*}, e1{*}
The template above describes a path where a product is viewed by Customer n1, and n1 owns card n2, then n2 makes a transfer named e1 to other cards.
- Rule No.2: Multiple edges and nodes with same filtering condition can be merged in a multiple-edge template.
For instance, a path of 4-node-3-edge can be put into this way: n().e().nf()[3].n(), resembling A-B path query template. Custom alias is not applicable in multiple-edge template.
n({@card.level == 1} as n1).re({@transfer}).nf({@card})[2].n({@card.level == 2} as n2) as p
return p{*}, n1{*}, n2{*}
The template above describes the 3-step transfer paths starting from a Card whose level is 1 to Card n1, and ending with Card n2 whose level is 2.
- Rule No.3: Set length of edge template as a range instead of a fixed number, to expand the query scope.
For instance, describe all paths within 10 steps by n().e().n().e()[:10].n():
n({@customer} as n1).re({@has}).n({@card} as c1)
.re({@transfer})[:10].n(c1) as p
return p{*}, n1{*}, c1{*}
The template above describes all possible paths where Customer n1 owns Card c1, c1 makes outbound transfers and finally transfers back to c1 within 10 steps.