====== From simple to advanced XL queries ====== This tutorial is more of a quiz than a tutorial, for the different type of queries a graph and a set of quests are provided. For each quest, the answer and an explanation is provided. Yet it is important to mention that there can be several solutions, for most of this problems. ===== Relational queries ===== module A; module B; module C; module D; protected void init () [ Axiom ==> A [A B [b1:B] c:C b2:B ] D C [B A A] B A,c />d:D,b1 /> b2, b2 /> d; ] |{{ :tutorials:graph_quest_path.png?800 |}}| | The graph created by the code above | **0. Get all nodes** __In a Context:__ ''%%(*Node*)%%'' __In a Query:__ ''%% Node ==> %%'' __Why:__ The query system in XL works based on the concept of object orientation from java, therefore a Query also selects all Objects, that extend the class used in the pattern. And since all Nodes in the graph extends the class Node... **1. Get all the A nodes** __In a Context:__ ''%%((*A*))%%'' __In a Query:__ ''%% A ==> %%'' **2. Get all B's that are linked by a successor** __In a Context:__ ''%%((*Node > B*))%%'' __In a Query:__ ''%% (*Node > *) B ==> ;%%'' __Selected Nodes:__ Model.B[id=30] Model.B[id=33] Model.B[id=39] __Why:__ The ''>'' arrow describes a successor connection and since Node addresses all Objects in the graph this query addresses all B's that are linked by an successor. For the Query, the use of the context syntax (''%%(*...*)%%'' is necessary to clarify that this part of the pattern is not suppose to be replaced. **3. Get all B's that are linked by a branch** __In a Context:__ ''%%((*Node +> B*))%%'' __In a Query:__ ''%% (*Node +> *) B ==> ;%%'' __Selected Nodes:__ Model.B[id=31] Model.B[id=36] __Why:__ The same as above only with the ''+>'' edge, which represents a branch **4. Get all As followed directly by another A** __In a Context:__ ''%%((*A -->A*))%%'' __In a Query:__ ''%% (*A --> *) A ==> ;%%'' __Selected Nodes:__ Model.A[id=29] Model.A[id=38] __Why:__ First of all in this case we know what type of parent we are looking for so the first Node is an A but we do not care about the edge and therefore we can use the ''%%-->%%'' term in the pattern which means all edges are possible. **5. Get As followed directly by another A, both are connected by a branch** __In a Context:__ ''%%((*A +>A*))%%'' __In a Query:__ ''%% (*A +> *) A ==> ;%%'' __Selected Nodes:__ Model.A[id=29] __Why:__ Same as above but only for branch edge. ** 6. Get all A's that are below a C** __In a Context:__ ''%% (*C (-->)* A*))%%'' __In a Query:__ ''%% (*C (-->)* *) A ==> ;%%'' __Selected Nodes:__ Model.A[id=37] Model.A[id=38] Model.A[id=40] __Why:__ Now we start at a C because we know at some point above our A there is suppose to be a C, moreover we know that the type of edge does not matter so we can use ''%%-->%%''. Finally we do not only look for the direct connection but for a range of connections this can be done by ''%%()*%%''. **7. Get all B's that are below another B** __In a Context:__ ''%% (*B (-->)+ B*))%%'' __In a Query:__ ''%% (*B (-->)+ *) B ==> ;%%'' __Selected Nodes:__ Model.B[id=31] Model.B[id=33] Model.B[id=33] Model.B[id=33] __Why:__ This is similar to the one above only that we have to make sure that the first B and the second B are not the same Node, To do so we use the (-->)+ pattern, which test any range of connections as well but with at least one edge. **8. Get all D which are below a C, where the C is below a B** __In a Context:__ ''%% (*B --> C --> D*))%%'' __In a Query:__ ''%% (*B --> C -->*) D ==> ;%%'' __Selected Nodes:__ Model.D[id=41] __Why:__ This follows the same concepts as before only with more than two nodes, if you want you can add as many as you want in a row like this. **9. Get All Nodes, which are connected upwards as following: Branch, Successor Branch** __In a Context:__ ''%%((*Node +> > +> Node*))%%'' __In a Query:__ ''%% (*Node +> > +>*) D ==> ;%%'' __Selected Nodes:__ Model.A[id=29] Model.B[id=31] __Why:__ If you don't care about the type of nodes but only the edges you can just skip the nodes in between. Only the first and the last place have to be a Node. **10. Get The B that is a decomposition child of another B, the successor of an C and has a D as a decomposition child.** __In a Context:__ ''%%((*B /> b:B, C > b,D*)b:B (*< C*),(*D ;%%'' __Selected Nodes:__ Model.B[id=33] __Why:__ - If you want to combine several conditions in a query you can concatenate them using the comma. - The '/>' edge describes a decomposition edge. - The differences in the two queries are only to highlight the different possibilities. **11. Get all A's that have no Children** __In a Context:__ ''%%((*a:A,(empty((*a --> Node*)))*))%%'' __In a Query:__ ''%% a:A,(empty((*a --> Node*))) ==>; %%'' __Selected Nodes:__ Model.A[id=38] Model.A[id=40] Besides the pattern of edges and nodes, it is also possible to add concatenate boolean conditions, if they are added in brackets (). In this case the boolean condition is actually the [[:groimp-platform:xl-builtin-methods|XL builtin method]] empty, which returns true if no the query inside does not find any match. **12. Get all the first B's after the A's** __In a Context:__ ''%%((* A (-->)+ : (B) *))%%'' ''%%((* A -minDescendants-> B *))%%'' ===== OOP Queries =====