2.13. Modifications, Additions and Deletions

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

2.13.1. Property Modifications

Modifications involve changing the values of properties in specific vertex, edge or table rows that match the 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 (a)-[e:EdgeFrame]->(b)
SET e.duration = b.time - a.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). Key properties of vertex and edge frames cannot be modified using SET operations.

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

xGT supports setting multiple properties at a time using a property map or assignment from another bound variable:

MATCH (a:SrcVertexFrame)-[e:EdgeFrame]->(b:TrgVertexFrame)
SET e = { duration : b.time - a.time, found : true, count : e.count + 1 }
SET b = a

The previous example sets multiple properties of the edge e using a property map. Non-key properties not appearing in the map will be set to NULL. The example also copies common non-key properties of a to b, that is the properties with common names and compatible types that appear in the schemas of both TrgVertexFrame and SrcVertexFrame. Properties of a that are not common to both will be set to NULL as well.

The operator += only sets properties appearing in the map or the other frame to those values, and keeps existing properties with their previous values:

MATCH (a:SrcVertexFrame)-[e:EdgeFrame]->(b:TrgVertexFrame)
SET e += { duration : b.time - a.time, found : true, count : e.count + 1 }
SET b += a

In this case, properties on the left-hand side that do not appear in the right-hand side will be conserved with their previous values instead of being set to NULL.

2.13.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.

Multiple-edge paths can also be specified in a CREATE. The following query would create new vertices if they didn’t already exist (as in a MERGE) and create the new edges given the specified path.

MATCH (a:VertexFrame)
WHERE a.id >= 0
CREATE (v1:VertexFrame { id: -1, data: "negative_vertex" })-
       [e1:EdgeFrame { float_count: -0.5, data: 10 }]->
       (v2:VertexFrame { id: -2, data: "negative_vertex" })-
       [e2:EdgeFrame { float_count: -0.5, data: 10 }]->
       (v3:VertexFrame { id: -3, data: "negatives_vertex" })

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.

2.13.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
DELETE e
RETURN e

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
DETACH DELETE a

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.

2.13.4. Row Additions and Deletions from Table Frames

xGT also supports changes to table frames using the same TQL clauses: CREATE and DELETE. Rows can be added to a table using the CREATE clause as follows:

CREATE (t:TableFrame { data_num: 10, data_str: "entry" })

If we use the CREATE clause with a MATCH query, then one row per matching answer is inserted into the table:

MATCH (v:VertexFrame)
WHERE v.id > 10
CREATE (t:TableFrame { data_num: v.id - 10, data_str: "entry" })

Rows can be deleted from the table frame by matching them first and the using the DELETE clause:

MATCH (t:TableFrame)
WHERE t.data_num < 10
DELETE t

In this example, rows with the data_num property less than 10 are deleted from the table.

2.13.5. Visibility of Changes

Property modifications, additions and deletions from frames are not immediately visible in the same query part in which they are executing. They are applied to the 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.