2.10. Property Extraction from Multiple Candidate Frames

xGT supports extracting properties from variables that can be bound to multiple frames. This is the case for multiple edge traversal steps, as well as when unwinding a path variable into its component path elements.

MATCH (:Companies)-[b:CompetesAgainst | :PartneredWith]->(:Companies)

In this example, the variable b can match an edge instance of the frames CompetesAgainst or PartneredWith. If both of those frames have a name property then the following constraint is valid:

MATCH (:Companies)-[b:CompetesAgainst | :PartneredWith]->(:Companies)
WHERE b.name STARTS WITH 'M'

This will match edge instances from the CompetesAgainst or PartneredWith frames that have names starting with the letter “M”.

For path variables, we must first unwind the path into its components.

MATCH p = ()-[:myedge0 | :myedge1 *1..10]->()
UNWIND p AS elem
RETURN elem.name

Once the path is unwound, we can use the variable introduced by the UNWIND clause to refer to properties in the frames that are part of the path. In this example, we are referring to the name property of the vertex and edge frames involved in the specified path.

2.10.1. Limitations on Multiple Frame Property Extraction

Properties extracted from multiple candidate frames are subject to the following constraints:

  • A property doesn’t have to exist on all the frames. If a property doesn’t exist on a frame, then it is substituted with the NULL value at query execution time.

  • A property must be of the same type or compatible types for all the frames it exists in.

  • The only compatible types are numerical types: integer and floating point.

If frame A has a property prop of type integer and frame B has a property with the same name of floating-point type, then the following query is well-formed:

MATCH ()-[ab : A | B]->()
WHERE ab.prop > 10

However, if the property of the same name has incompatible types in the candidate frames, then the TQL compiler will reject the query (in this case, the frame myedge0 has a property prop of text type, while it’s a integer on frame myedge1):

MATCH p = ()-[:myedge0 | :myedge1 *1..10]->()
UNWIND p AS elem
RETURN elem.prop + 1.0

If a property with that name does not exist on a candidate frame, then it is substituted with the NULL value at query execution time, allowing the query to run:

MATCH p = (:Person)-[:WorksFor]->(:Company)
UNWIND p AS elem
RETURN elem.first_name

In this example, only the Person frame has a property first_name. The WorksFor and Company frames do not have that property, thus the value is substituted with NULL in the returned rows.