PGX 20.1.1
Documentation

Graph Builder and Graph Change Set

This section explains the API of the GraphBuilder interface used for creating graphs from scratch and the GraphChangeSet interface used for modifying loaded graphs.

Creating Graphs from Scratch (GraphBuilder)

To create a graph from scratch, the user first needs to acquire a graph builder, which accumulates all of the new vertices and edges. The basic workflow for creating graphs from scratch is:

  1. Acquire a modifiable graph builder
  2. Add vertices and edges to the graph builder
  3. Create a fixed PgxGraph out of the accumulated changes

The following methods in PgxSession can be used to create a graph builder:

GraphBuilder<Integer> newGraphBuilder()
<ID extends Comparable<ID>> GraphBuilder<ID> newGraphBuilder(IdType idType)
GraphBuilder<Integer> createGraphBuilder(IdGenerationStrategy vertexIdGenerationStrategy, IdGenerationStrategy edgeIdGenerationStrategy)
<ID extends Comparable<ID>> GraphBuilder<ID> createGraphBuilder(IdType idType, IdGenerationStrategy vertexIdGenerationStrategy, IdGenerationStrategy edgeIdGenerationStrategy)

The first version without an argument will create a default graph builder with the vertex ID type integer.
The second version takes one argument idType which defines the vertex ID type of the resulting GraphBuilder instance.
The third and fourth versions are similar to first and second, respectively. They take two additional arguments vertexIdGenerationStrategy and edgeIdGenerationStrategy, which define the ID generation strategy

The GraphBuilder class itself has the following methods for adding vertices and edges, as well as for building the resulting graph.

VertexBuilder<VID> addVertex(VID vertexId)
VertexBuilder<VID> addVertex()
EdgeBuilder<VID> addEdge(long edgeId, VID srcVertex, VID dstVertex)
EdgeBuilder<VID> addEdge(VID srcVertex, VID dstVertex)
EdgeBuilder<VID> addEdge(long edgeId, VertexBuilder<VID> srcVertex, VertexBuilder<VID> dstVertex)
EdgeBuilder<VID> addEdge(VertexBuilder<VID> srcVertex, VertexBuilder<VID> dstVertex

GraphBuilder<VID> resetVertex(VID vertexId)
GraphBuilder<VID> resetVertex(VertexBuilder<VID> vertex)
GraphBuilder<VID> resetEdge(long edgeId)

Adding Vertices and Edges

PGX supports two different generation strategies for adding vertices and edges to a changeset, depending on the IdGenerationStrategy parameter: USER_IDS or AUTO_GENERATED. In the USER_IDS strategy, the user is responsible for passing the desired ID for the newly added entity as the first parameter to the addVertex() or addEdge() methods. The chosen ID must be unique in the graph (i.e., no other entity with the same ID may exist in the graph already). In the AUTO_GENERATED strategy, the user can omit the first parameter of the addVertex() or addEdge() methods and PGX takes care of generating a unique ID for the newly added entity.

Edges can be added with one of the addEdge methods. Similar to the vertexId, an edgeId needs to be unique.

The second and third argument of addEdge are descriptions of the source and destination vertices, respectively. There are two ways to specify these vertices:

  • By their vertex ID
  • By an instance of a VertexBuilder which was acquired previously with a call to addVertex

The second method can be useful if the vertex IDs are particularly complicated or long. For example:

GraphBuilder<String> builder = session.newGraphBuilder(IdType.STRING);

VertexBuilder<String> v1 = builder.addVertex("long named vertex 1");
VertexBuilder<String> v2 = builder.addVertex("long named vertex 2");

builder.addEdge(0, v1, v2);

If addEdge is called with vertices that have not been created with a call to addVertex before, they will be added on the fly.

Resetting Added Vertices and Edges

Added vertices and edges can be removed from the graph builder by calling one of the appropriate reset methods.

Calling resetVertex will remove the vertex with the given vertexId or the given VertexBuilder instance and all connected edges from the graph builder.

Similarly, calling resetEdge will remove the edge with the given edgeId from the graph builder.

After a vertex or edge has been reset, the vertexId or edgeId is again free to use for this graph builder instance.

Adding Properties and Labels

The method addVertex will return a VertexBuilder for that specific vertex. It can be used to add property values to the vertex. The VertexBuilder provides the following methods:

VertexBuilder<VID> setProperty(String key, Object value)
VertexBuilder<VID> addLabel(String label)
VID getId()

Property values can be added to the given vertex using the setProperty method. It takes the name of the property as first argument and the value of the property as the second.

Labels can be added using the addLabel method which takes the new label as argument.

Properties are not required to be declared before values can be assigned to them. The first mention of a property will also define its type, which is deduced from the value.

The table below shows the mapping between Java classes and PGX property types.

PGX property type Java class
BOOLEAN boolean
INTEGER int
FLOAT float
LONG long
DOUBLE double
STRING String
LOCAL_DATE java.time.LocalDate
TIME java.time.LocalTime
TIMESTAMP java.time.LocalDateTime
TIME_WITH_TIMEZONE java.time.OffsetTime
TIMESTAMP_WITH_TIMEZONE java.time.OffsetDateTime
POINT2D oracle.pgql.lang.spatial.Point2D

Take for example the following code:

GraphBuilder<Integer> builder = session.newGraphBuilder();
VertexBuilder<Integer> vertex = builder.addVertex(1);

vertex.setProperty("intProp", 10);
vertex.setProperty("strProp", "str");

The property intProp will now have the type integer for this graph builder, as the first value assigned to it was an integer. Similarly the property strProp will have the type string.

Once the type of a property has been defined, it cannot be changed anymore and any calls to setProperty with a value of the wrong type will result in an exception.

The method getId returns the vertex ID of the vertex this builder belongs to.

Similarly the method addEdge returns an EdgeBuilder which works in the same way as the VertexBuilder. This is the interface of EdgeBuilder:

EdgeBuilder<VID> setProperty(String key, Object value)
EdgeBuilder<VID> setLabel(String label)
long getId()

The methods setProperty and getId are already known from the VertexBuilder and work similarly. One additional method setLabel is provided, which can be used to set an optional edge label for each edge.

Building the Graph

After all vertices, edges and property values have been added, the graph can be constructed using one of the following asynchronous buildAsync methods or their equivalent, synchronous build methods:

PgxFuture<PgxGraph> buildAsync(String newGraphName)
PgxFuture<PgxGraph> buildAsync()

PgxGraph build(String newGraphName)
PgxGraph build()

Optionally a name for the graph can be specified using the first argument of buildAsync. If no name is provided or the name is null, a unique name will be generated.

Furthermore, it is possible to create a new snapshot of the same graph out of the ChangeSet by calling

PgxFuture<PgxGraph> buildNewSnapshotAsync()

PgxGraph buildNewSnapshot()

For more information on this capability, you can refer to Graph Versioning.

Builder Interface

The GraphBuilder API is designed as a builder similar to the API for building graph configuration objects. Multiple calls to add vertices and edges and setting their properties can be chained together.

If we want to add three vertices and three edges with a property each this can be written like in the following example:

PgxGraph graph = session.newGraphBuilder()
  .addVertex(1).setProperty("prop", 1)
  .addVertex(2).setProperty("prop", 2)
  .addvertex(3).setProperty("prop", 3)
  .addEdge(1, 1, 2).setProperty("cost", 0.1)
  .addEdge(2, 2, 3).setProperty("cost", 0.2)
  .addEdge(3, 3, 1).setProperty("cost", 0.3)
  .build();

For more information about the graph builder, please see the graph builder tutorial and the javadocs.

Modifying Loaded Graphs (GraphChangeSet)

A loaded graph can be modified using a graph change set, which is a concept similar to the graph builder, but with extended capabilities for modifying and removing vertices and edges.

PGX 20.1.1 limitation

Modifying undirected graphs is not supported.

The basic workflow for changing a graph is:

  1. Get a graph change set for the graph that needs to be modified
  2. Apply changes to the graph change set
  3. Create a fixed PgxGraph out of the graph change set

The class PgxGraph offers the following methods to create an empty graph change set:

<ID extends Comparable<ID>> GraphChangeSet<ID> createChangeSet()
<ID extends Comparable<ID>> GraphChangeSet<ID> createChangeSet(IdGenerationStrategy vertexIdGenerationStrategy, IdGenerationStrategy edgeIdGenerationStrategy)

The GraphChangeSet interface derives directly from GraphBuilder, which means that all operations that are available in the graph builder are also available in the graph change set.

Additionally methods for updating and removing vertices and edges are available.

Updating Vertices and Edges

The following methods are available for updating vertices and edges:

VertexModifier<VID> updateVertex(VID vertexId)
EdgeModifier<VID> updateEdge(long edgeId)

To update vertices, updateVertex needs to be called with the ID of the vertex that is updated as first argument. The method returns a VertexModifier which offers the same methods for changing properties as the VertexBuilder.

Similarly the updateEdge method takes the ID of the edge that is updated as first argument and returns an EdgeModifier.

Note that if the vertex or edge ID does not exist in the original graph, an exception is thrown as soon as the graph is built.

Removing Vertices and Edges

GraphChangeSet<VID> removeVertex(VID vertexId)
GraphChangeSet<VID> removeEdge(long edgeId)

Vertices can be removed using the removeVertex method which takes the ID of the vertex to be removed as first argument. A vertex with the given ID needs to exist in the original graph, otherwise an exception is thrown once the graph is built.

Additionally this call will remove all adjacent edges of this vertex. The adjacent edges will be removed once the graph is built.

Edges can be removed similarly with the removeEdge method which takes an edge ID as the first argument instead. Likewise, an edge with the given ID needs to exist in the original graph.

Partitioned Graphs

It is possible to update partitioned graphs using a GraphChangeSet. The following limitations apply:

  • Only graphs loaded with the IdStrategy set to KEYS_AS_IDS are supported.
  • Only changesets with IdGenerationStrategy set to USER_IDS for both vertices and edges are supported.
  • It is not possible to add new properties.
  • It is also not possible to add new label values to vertices or edges.
  • A tight coupling between vertex/edge label and original data source provider exists:
    • When adding a vertex (resp. edge) you must indicate all the labels that are associated to the vertex provider (resp. edge provider) in which they should be added to
    • Additionally for edges the source and destination vertices must have all the labels associated to the respective vertex provider they are in.

Example: Given a graph that was loaded from the vertex providers "student" and "university", and the edge providers "knows" (from "student" to "student") and "studiesAt" (from "student" to "university"):

The following example shows a well-formed changeset:

GraphChangeSet changeSet = graph.createChangeSet(IdGenerationStrategy.USER_IDS, IdGenerationStrategy.USER_IDS);

// add vertex with ID 123 with label "student" and property "name" set to "Jane"
VertexBuilder srcVertex = changeSet.addVertex(123).addLabel("student").setProperty("name", "Jane");

// add vertex with ID "UCSF" with label "university" and property "location" set to "SF"
VertexBuilder dstVertex = changeSet.addVertex("UCSF").addLabel("university").setProperty("location", "SF");

// add edge from a srcVertex to dstVertex with label "studentAt" with ID "5L"
changeSet.addEdge(5L, srcVertex, dstVertex ).setLabel("studentAt")

// remove a vertex by ID
changeSet.removeVertex(456);

// remove an edge by ID
changeSet.removeEdge(4L);

// build new graph
newGraph = changeSet.build();

The following examples are invalid:

// label "person" does not exist in the original graph
changeSet.addVertex(1).addLabel("person")

// property "age" does not exist in the original graph
changeSet.addVertex(2).addLabel("student").setProperty("age", 23);

// no label provided
changeSet.addVertex(3);
changeSet.addEdge(4L, srcVertex, dstVertex);

// adding an edge between vertices that the original edge provider could not hold
// the edge provider "knows" is defined between "student" and "student", not "student" and "university", so the following won't work:
VertexBuilder srcVertex = changeSet.addVertex(123).addLabel("person");
VertexBuilder dstVertex = changeSet.addVertex("UCSF").addLabel("university");
changeSet.addEdge(5L, srcVertex, dstVertex).addLabel("knows");

Building the Graph

After all changes have been made to the graph change set, the graph can be constructed using the same build methods as used by the graph builder. Note that building a graph change set will create a new copy of the graph with all the modifications applied. The changes will not be applied in-place.

For more information about the graph change set, please consult the tutorial and the javadocs.