4.12. TQL Modifications, Additions and Deletions

These optional parts of a query allow for changes to happen to the graph as part of its execution.

4.12.1. Property Modifications

Modifications involve changing the values of properties in specific vertex and/or edge instances that match the graph pattern declared in the query. Note that the properties themselves must have been declared as part of the respective frame creation.

The power of these property modifications is that the values to modify them to can be computed from the query itself. That is, the user can programmatically determine what to change the values to as part of the query. A simple example of this would be computing a duration for each edge, assuming that all the edges have a start_time and end_time property:

MATCH ()-[e:EdgeFrame]->()
SET e.duration = e.end_time - e.start_time

In this case, all edges belonging to the frame EdgeFrame are visited (there are no WHERE constraints) and duration is computed from two of the other properties on that edge. Note that the schema for EdgeFrame must already include a duration property (even if the values are null).

Note that property modification requires a structure description (MATCH pattern) for the query since it must first find the elements in the graph before being able to modify them.

4.12.2. Topology Additions

Additions to the graph can also be done as part of query execution. It is possible to add new vertices and/or edges as part of a query.

Additions of new vertices is simpler since it involves providing the name of the vertex frame to add the vertex to as well as at least enough values for the key properties of the vertex:

MATCH ()-[e:EdgeFrame]->()
CREATE (v:VertexFrame { id: e.source_id + 1000, data: "test" })

In this simple example a new vertex is created for each source endpoint of an edge in the EdgeFrame frame. The value of the vertex key is computed from the key of the source endpoint of the edge. This example assumes that the computed vertex key (id) is outside the range of existing vertices in the vertex frame. Note that it is an error to try and create a vertex with the same key value as an existing vertex in the same frame.

In addition to supporting the CREATE keyword, TQL supports the MERGE keyword which indicates to the system that the vertex should be created if it does not exist or retrieved from the current data store if it does. As with the CREATE keyword the MERGE keyword requires the specification of at least the key properties for the merged vertex. The example below illustrates the use of the MERGE keyword when the non-existence of entries with the same key value on the vertex frame cannot be guaranteed.

MATCH ()-[e:EdgeFrame]->()
MERGE (v:VertexFrame { id: e.source_id + 1000, data: "test" })

Adding an edge involves matching existing vertices to use as endpoints for the edge being created:

MATCH (a:VertexFrame)-(:EdgeFrame)->(b:VertexFrame)
WHERE a.id > 0 AND b <> a
CREATE (a)-[new_edge:EdgeFrame { float_count: -0.5, data: 10 }]->(a)

In this example, we create a self-edge from a to itself and add it to the edge frame EdgeFrame, for distinct pairs of vertices a and b, where a’s identifier is positive and there is an edge already in EdgeFrame from a to b. Note that the specification of the properties of the newly created edge cannot include the values of key properties – those are derived from values of the key properties of the endpoints.

The endpoints of the created vertex can be any pair of vertices that is compatible with the declaration of the edge frame (that they are of the right vertex frame for the source and target of the edge frame). The only requirement is that the endpoints have to be matched as part of the query. For convenience, the direction of the edge can be specified in either sense: source-to-target or target-from-source, with the resulting created edge being the same.

While xGT does not currently support the creation of the vertex endpoints of an edge and the edge itself in the same query statement, combining MERGE on a vertex and CREATE on the edge can be used to achieve the same effect:

MATCH (a:VertexFrame)
WHERE a.id >= 0
MERGE (b:VertexFrame { id: -1, data: "negative_vertex" })
CREATE (b)-[new_edge:EdgeFrame { float_count: -0.5, data: 10 }]->(a)

In this example, we match an existing vertex a with non-negative key property id, then create a vertex with the key id (if necessary), and finally use that vertex to create a new edge from it to the originally-matched a vertex. Note that MERGE is only supported for vertices because multiple edges can exist for the same key property values. It would be ambiguous if more than one edge matched.

The following example illustrates the optionality of the MATCH pattern (or structure description) to add elements to the graph:

MERGE (a:VertexFrame { id: 0, data: "target vertex" })
MERGE (b:VertexFrame { id: -1, data: "negative vertex" })
CREATE (b)-[new_edge:EdgeFrame { float_count: -0.5, data: 10 }]->(a)

In this case, we MERGE two possibly new vertices with keys 0 and -1 and then proceed to use those vertices to create a new edge between them. The MATCH pattern becomes optional because we know exactly the constant key values (id property in this example) that we want the vertices to have. The limitation on not using a MATCH pattern is that the number of vertices and edges created is limited to the ones literally described in the syntactic query. When a MATCH pattern is used, the multiplicity of vertices and edges created is driven by the number of elements in the results set of the query.

4.12.3. Topology Deletions

Deletions from the graph can also be done as part of query execution. It is possible to delete vertices and/or edges as part of a query.

Deleting edges is a simpler process than deleting vertices, because it is localized to the affected edge frame:

MATCH ()-[e:EdgeFrame]->()
WHERE e.sid = 0 AND e.tid = -1

In this case, the matched edges are removed from the edge frame as part of the query execution. Note that it is still possible to return values from the deleted edges since deletion occurs after matches have already been recorded (as in this example where e is returned).

Deleting a vertex from a vertex frame is a more involved process since there could still be edges incident on that vertex across a collection of different frames.

MATCH (a:VertexFrame)
WHERE a.id = 0

TQL uses DETACH DELETE (as opposed to just DELETE) to delete a vertex and all adjacent edges. In this case, even if just the vertex frame VertexFrame is specified in the query, xGT will have to look into all edge frames where VertexFrame is a source or a target and delete edges from them that are incident on the matching vertex a.

Consider the case where a user does not have visibility (see Access Control) to all the incident edges of a vertex. In such a situation, the user has requested the deletion of at least one edge that they do not have the permission to delete. Thus, the query will fail and the transaction will roll back with a security violation.

Note that topology deletions do require a structure description (MATCH pattern) for a query since the query must first find the requested elements before deleting them from the graph. It is not possible to specify deletion of a vertex or edge without a MATCH pattern in the query.

4.12.4. Visibility of Changes to the Graph

Property modifications, additions and deletions from the graph are not immediately visible in the same query part in which they are executing. They are applied to the graph and all its frames as part of the final steps in query part execution after the pattern matching and query results have been recorded.

They are fully available in subsequent query parts. More information is provided in the document titled Transactions in xGT.