**************************** Building Graphs from Scratch **************************** For small example graphs the effort of writing the graph data to a file and loading it with a configuration might be too big. This guide shows an alternative way of creating graphs using the GraphBuilder interface. This interface allows users to create small graphs programmatically. .. note:: Graph builder API might not be suitable when creating a large graph instance. The execution time of this API is strictly proportional to the size of the graph that is being created as well as communication bandwidth between the client and the server. Creating a Simple Graph ----------------------- The starting point for creating graphs is the :class:`GraphBuilder` class which accumulates the vertex and edge data of the new graph. After all changes have been added a :class:`PgxGraph` can be created out of the accumulated vertices and edges. the :class:`GraphBuilder` supports two generation strategies for creating vertices and edges IDs: ``user_ids`` (the default value) and ``auto_generated``. Let us see how that works by creating the simple sample graph: .. code-block:: python :linenos: from pypgx import get_session session = get_session(session_name="example") builder = session.create_graph_builder() builder.add_edge(1, 2) builder.add_edge(2, 3) builder.add_edge(2, 4) builder.add_edge(3, 4) builder.add_edge(4, 2) There are a couple of things to notice here: First, a call to :meth:`add_edge` consists of the new, unique edge ID, the source vertex ID and the destination vertex ID. Second, no graph config is needed. Everything needed to know is extracted from the data that is available. Third, notice that we only added edges and did not add any vertices. This is because any vertices that not already exist will be added on the fly as edges are created. The resulting graph is a session bound, **transient** graph, which can be queried and analyzed just as if the graph was loaded from a file. The graph can also be stored to a file in a format recognized by PGX. See the Store :ref:`Storing a Graph to Disk ` guide for more information on that. Adding a Vertex Property ------------------------ Now, how does the code look like if we want to add a vertex property? For this the GraphBuilder offers a fluid interface: .. code-block:: python :linenos: from pypgx import get_session session = get_session(session_name="example") builder = session.create_graph_builder() builder.add_vertex(1).set_property("double-prop", 0.1) builder.add_vertex(2).set_property("double-prop", 2.0) builder.add_vertex(3).set_property("double-prop", 0.3) builder.add_vertex(4).set_property("double-prop", 4.56789) builder.add_edge(1, 2) builder.add_edge(2, 3) builder.add_edge(2, 4) builder.add_edge(3, 4) builder.add_edge(4, 2) graph = builder.build() Now we need to add the vertices separately, as we want to assign property values to them. As previously stated, we don't need to write a graph config. Therefore we do not need to specify the type of the property anywhere. The type of a property is automatically determined from the value of the first mention of the property. If the value for a property is missing for a vertex or edge, a default value is assumed. This is ``0`` (or the respective equivalent) for numeric properties, ``False`` for boolean properties, ``1.1.1970 00:00:00`` for date properties and ``None`` for string properties. Multiple calls to :meth:`set_property` can be chained to set multiple property values at once. Use Strings as Vertex Identifiers --------------------------------- All of the previous examples had ``integer`` vertex IDs to identify a vertex, which is the default in PGX. As with graphs loaded from file or database, the type of the vertex ID can also be a ``long`` or a ``string``. For this we need to specify the vertex ID type when we create the GraphBuilder. Let's recreate the graph with string vertex IDs: .. code-block:: python :linenos: from pypgx import get_session session = get_session(session_name="example") builder = session.create_graph_builder(id_type='string') builder.add_vertex("vertex 1").set_property("double-prop", 0.1) builder.add_vertex("vertex 2").set_property("double-prop", 2.0) builder.add_vertex("vertex 3").set_property("double-prop", 0.3) builder.add_vertex("vertex 4").set_property("double-prop", 4.56789) builder.add_edge("vertex 1", "vertex 2") builder.add_edge("vertex 2", "vertex 3") builder.add_edge("vertex 2", "vertex 4") builder.add_edge("vertex 3", "vertex 4") builder.add_edge("vertex 4", "vertex 2") graph = builder.build() Shortcut for Creating Edges with Previously Created Vertices ------------------------------------------------------------ As it can be very repetative to always enter the full vertex ID when adding an edge, a shortcut can be used. For this a reference to the vertex can be obtained as it is created which can be used in the :meth:`add_edge` statement afterwards. .. code-block:: python :linenos: from pypgx import get_session session = get_session(session_name="example") builder = session.create_graph_builder(id_type='string') v1 = builder.add_vertex("vertex 1").set_property("double-prop", 0.1) v2 = builder.add_vertex("vertex 2").set_property("double-prop", 2.0) v3 = builder.add_vertex("vertex 3").set_property("double-prop", 0.3) v4 = builder.add_vertex("vertex 4").set_property("double-prop", 4.56789) builder.add_edge(v1, v2) builder.add_edge(v2, v3) builder.add_edge(v2, v4) builder.add_edge(v3, v4) builder.add_edge(v4, v2) graph = builder.build() Add an Edge Property and Label ------------------------------ Finally, we want to add an edge property and an edge label to the graph. .. code-block:: python :linenos: from pypgx import get_session session = get_session(session_name="example") builder = session.create_graph_builder(id_type='string') v1 = builder.add_vertex("vertex 1").set_property("double-prop", 0.1) v2 = builder.add_vertex("vertex 2").set_property("double-prop", 2.0) v3 = builder.add_vertex("vertex 3").set_property("double-prop", 0.3) v4 = builder.add_vertex("vertex 4").set_property("double-prop", 4.56789) builder.add_edge(v1, v2).set_property( "edge-prop", "edge_prop_1_2").set_label("label") builder.add_edge(v2, v3).set_property( "edge-prop", "edge_prop_2_3").set_label("label") builder.add_edge(v2, v4).set_property( "edge-prop", "edge_prop_2_4").set_label("label") builder.add_edge(v3, v4).set_property( "edge-prop", "edge_prop_3_4").set_label("label") builder.add_edge(v4, v2).set_property( "edge-prop", "edge_prop_4_2").set_label("label") graph = builder.build() Use GraphBuilder with implicit IDs ---------------------------------- The :class:`GraphBuilder` supports an ``auto_generated`` generation strategy that allows to omit the edge / vertex IDs. In this generation strategy, PGX will automatically assign IDs to the entities being added to the changeset. The following example illustrates the GraphBuilder by creating a graph with three vertices and three edges. .. code-block:: python :linenos: from pypgx import get_session session = get_session(session_name="example") builder = session.create_graph_builder( id_type='string', vertex_id_generation_strategy="auto_generated" ) v1 = builder.add_vertex() v2 = builder.add_vertex() v3 = builder.add_vertex() builder.add_edge(v1, v2) builder.add_edge(v1, v3) builder.add_edge(v3, v2) graph = builder.build()