<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Wendel Fernandes de Lana</title>
    <description>The latest articles on DEV Community by Wendel Fernandes de Lana (@wendellana).</description>
    <link>https://dev.to/wendellana</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1045418%2Fcc30a302-d827-4cd5-b1f5-7fd6af91bba0.jpeg</url>
      <title>DEV Community: Wendel Fernandes de Lana</title>
      <link>https://dev.to/wendellana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wendellana"/>
    <language>en</language>
    <item>
      <title>Graph Generation Algorithms</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Fri, 01 Sep 2023 00:20:03 +0000</pubDate>
      <link>https://dev.to/wendellana/graph-generation-algorithms-4lp5</link>
      <guid>https://dev.to/wendellana/graph-generation-algorithms-4lp5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Apache AGE is a popular graph database management system that excels at handling and querying highly connected data, making it an excellent choice for graph-based applications. A graph generation algorithm for Apache AGE can offer several benefits for various applications and use cases. In this article, I'm going to discuss some of these use cases and how this feature is an important advantage in a graph database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applications and Advantages
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Graph Data Generation&lt;/strong&gt;: it can create synthetic graph data for testing and benchmarking purposes. This is particularly useful for evaluating the performance of graph queries, optimizing database schema design, and simulating real-world scenarios without relying on actual data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Machine Learning and Data Analysis&lt;/strong&gt;: generated graph data can be used for machine learning tasks and data analysis within Apache AGE. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing and Evaluation&lt;/strong&gt;: it proves valuable for assessing the efficiency and effectiveness of functions integrated into Apache AGE. By crafting graphs with predefined attributes, it simplifies the validation of algorithm accuracy and performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy and Security&lt;/strong&gt;: in scenarios where sharing sensitive data directly isn't viable, graph generation algorithms step in to yield cleansed or anonymized graph data while upholding the fundamental graph structure. This proves invaluable for disseminating data for research or collaboration without compromising security and privacy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Educational and Training Purposes&lt;/strong&gt;: it can be used as educational aids to facilitates the teaching of graph concepts, algorithms, graph database queries and even fundamental mathematical theorems like the Watts-Strogatz model and the Barbell graph. This approach significantly improves the learning of graph theory within the context of Apache AGE.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Graph generation algorithms can be used in several different situations and for multiple purposes, making them an important feature in graph databases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contribute
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://age.apache.org/age-manual/master/index.html"&gt;Apache AGE documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/apache/age"&gt;Apache AGE repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://age.apache.org"&gt;Apache AGE website&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>algorithms</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introduction to Apache AGE</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Fri, 18 Aug 2023 18:44:47 +0000</pubDate>
      <link>https://dev.to/wendellana/introduction-to-apache-age-38g6</link>
      <guid>https://dev.to/wendellana/introduction-to-apache-age-38g6</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;What is Apache AGE?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://age.apache.org/"&gt;Apache AGE&lt;/a&gt; is a PostgreSQL extension that provides graph database functionality. Therefore, it encompasses the Postgres functionalities while incorporating Cypher for graph management. This unique combination empowers you with access to advanced graph query modeling within the framework of your relational database infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Definitions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Vertex (node)&lt;/strong&gt;&lt;br&gt;
It serves as a container for storing entity-related data, potentially encompassing multiple properties. Notably, each vertex can accommodate a variety of properties, yet it is restricted to possessing a singular label designation.&lt;br&gt;
&lt;strong&gt;Edge (relationship)&lt;/strong&gt;&lt;br&gt;
An edge links nodes in a graph, defining a distinct relationship or interaction with defining attributes. This is vital for navigating intricate interconnections in the graph data model.&lt;br&gt;
&lt;strong&gt;Path&lt;/strong&gt;&lt;br&gt;
The path represents a sequence of connected edges and nodes. It captures the route or journey between entities, enabling the exploration of relationships and patterns within the graph.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Common Clauses using Cypher&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CREATE&lt;/strong&gt;: used to add new nodes and edges to the graph.&lt;br&gt;
&lt;strong&gt;DELETE&lt;/strong&gt;:  is used to remove nodes, edges, or entire paths from the graph.&lt;br&gt;
&lt;strong&gt;MATCH&lt;/strong&gt;: used to retrieve data from the graph database. It allows you to specify patterns of nodes and edges, facilitating the discovery of interconnected entities and relationships.&lt;br&gt;
&lt;strong&gt;MERGE&lt;/strong&gt;: allows you to either create new nodes and edges or match and update existing ones based on specified patterns.&lt;br&gt;
&lt;strong&gt;REMOVE&lt;/strong&gt;: used to remove properties from vertex and edges.&lt;br&gt;
&lt;strong&gt;RETURN&lt;/strong&gt;: specify what data you want to retrieve as a result of your query. It allows you to define the attributes or properties of nodes and edges that you're interested in.&lt;br&gt;
&lt;strong&gt;SET&lt;/strong&gt;: used to update properties of nodes or edges within the graph.&lt;br&gt;
&lt;strong&gt;WHERE&lt;/strong&gt;: filters the results of a query based on specified conditions. It helps you narrow down your search and retrieve only the data that meets specific criteria.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Examples&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Create a vertex without label and returns it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    CREATE (v) 
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns all vertices&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    MATCH (v) 
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a vertex with a property&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    CREATE (v {property: 'value'})
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Return the vertex with the specified value&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    MATCH (v {property: 'value'}) 
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Return the vertex with the specified value using WHERE&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    MATCH (v)
    WHERE v.property = 'value'
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delete all vertices&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    MATCH (v) 
    DELETE v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a vertex with a label and properties&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    CREATE (v:Label {property1: 1, property2: 'value', property3: true}) 
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get all vertices with a specified label&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    MATCH (v:Label) 
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the vertex with the label and change the value of its property&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    MATCH (v:Label)
    SET v.property1 = 0
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove the third property&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    MATCH (v:Label)
    REMOVE v.property3
    RETURN v
$$) AS (vertex agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating a new vertex and a relationship with our already existing node, returning the created path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM cypher('graph_name', $$ 
    MERGE p=(x:Label)-[r:relationship]-&amp;gt;(y:newNode)
    RETURN p
$$) AS (path agtype);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  References and manual
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://age.apache.org/age-manual/master/index.html"&gt;Apache AGE documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/apache/age"&gt;Apache AGE repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://age.apache.org"&gt;Apache AGE website&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>beginners</category>
      <category>database</category>
      <category>postgres</category>
    </item>
    <item>
      <title>How to export data from Apache AGE</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Wed, 12 Jul 2023 01:55:55 +0000</pubDate>
      <link>https://dev.to/wendellana/how-to-export-data-from-apache-age-9m2</link>
      <guid>https://dev.to/wendellana/how-to-export-data-from-apache-age-9m2</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Exporting data from Apache AGE, an extension of PostgreSQL for graph data, can be a valuable task when you need to analyze or share your graph data with other systems. In this blog post, we will explore the process of exporting both edges and nodes from Apache AGE using the COPY command. By following the steps outlined below, you'll be able to export your graph data into CSV files for further analysis or integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Exporting Edges&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To export edges from Apache AGE, you can utilize the COPY command with a Cypher query. The following command allows you to export the edges to a CSV file:&lt;br&gt;
&lt;code&gt;COPY (SELECT * FROM cypher('graph_name', $$&lt;br&gt;
    MATCH (a)-[e]-&amp;gt;(b)&lt;br&gt;
    RETURN start_id(e), label(a), end_id(e), label(b) $$)&lt;br&gt;
    AS (start_id agtype, start_vertex_type agtype, end_id agtype, end_vertex_type agtype)&lt;br&gt;
) TO '/path_to_csv/edges_graph.csv' DELIMITER ',' CSV HEADER;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command executes a Cypher query that retrieves the desired edge information from the specified graph name. It selects the start ID, start vertex label, end ID, and end vertex label. The results are then written to a CSV file specified by the file path '/path_to_csv/edges_graph.csv' with a comma delimiter and a header row.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Exporting Nodes&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Exporting nodes from Apache AGE requires manually retrieving the node properties and defining the column list as the CSV header. Let's assume we have a person vertex with properties like id, name, and age. To export this vertex, follow the code snippet below:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;COPY (SELECT * FROM cypher('graph_name', $$&lt;br&gt;
    MATCH (a)&lt;br&gt;
    RETURN a.id, a.name, a.age $$)&lt;br&gt;
    AS (id agtype, name agtype, age agtype)&lt;br&gt;
) TO '/path_to_csv/person_vertex_graph.csv' DELIMITER ',' CSV HEADER;&lt;/code&gt;&lt;br&gt;
In this example, we execute a Cypher query that matches all nodes of the desired type (person). The query retrieves the node's ID, name, and age properties. The results are then written to a CSV file specified by the file path '/path_to_csv/person_vertex_graph.csv' with a comma delimiter and a header row that lists the column names.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Exporting data from Apache AGE is a straightforward process that allows you to extract graph data and save it in CSV format. By utilizing the COPY command and crafting appropriate Cypher queries, you can export both edges and nodes from your Apache AGE graph database. This exported data can then be utilized for various purposes, such as further analysis, integration with other systems, or sharing with collaborators.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Contribute&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/age"&gt;Apache AGE repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://age.apache.org"&gt;Apache AGE website&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>programming</category>
      <category>postgres</category>
      <category>learning</category>
    </item>
    <item>
      <title>Apache AGE: Watts-Strogatz Graph</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Fri, 02 Jun 2023 16:22:44 +0000</pubDate>
      <link>https://dev.to/wendellana/apache-age-watts-strogatz-graph-53h1</link>
      <guid>https://dev.to/wendellana/apache-age-watts-strogatz-graph-53h1</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We will discuss in this post about the Watts-Strogatz graph, a feature that I've worked for Apache AGE and you can see the Pull Request for it &lt;a href="https://github.com/AGEDB-INC/postgraph/pull/139"&gt;here&lt;/a&gt;. First, let's introduce what is Apache AGE and Watts-Strogatz graph.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Apache AGE&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Apache AGE is a PostgreSQL extension that provides graph database functionality. The goal of the project is to create single storage that can handle both relational and graph model data so that users can use standard ANSI SQL along with openCypher, the Graph query language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contribute to Apache AGE&lt;/strong&gt;&lt;br&gt;
Website: &lt;a href="https://age.apache.org"&gt;https://age.apache.org&lt;/a&gt;&lt;br&gt;
Github: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;What is Watts-Strogatz Graph&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Watts–Strogatz model was proposed by Duncan J. Watts and Steven Strogatz in their article published in 1998 in the Nature scientific journal. It is a random graph generation model that produces graphs with small-world properties, including short average path lengths and high clustering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How the algorithm works&lt;/strong&gt;&lt;br&gt;
First create a ring over &lt;strong&gt;n&lt;/strong&gt; nodes. Then each node in the ring is joined to its &lt;strong&gt;k&lt;/strong&gt; nearest neighbors (or k-1 neighbors if k is odd). Then shortcuts are created by replacing some edges as follows: for each edge (u,v) in the underlying “n-ring with k nearest neighbors” with probability &lt;strong&gt;p&lt;/strong&gt; replace it with a new edge (u,w) with uniformly random choice of existing node w.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Creating Watts-Strogatz Graph&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here is the syntax of the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;age_create_watts_strogatz_graph(graph_name Name, n int, k int, p float
                                vertex_label_name Name DEFAULT = NULL,
                                vertex_properties agtype DEFAULT = NULL,
                                edge_label_name Name DEAULT = NULL,
                                edge_properties agtype DEFAULT = NULL,
                                bidirectional bool DEFAULT = true)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;graph_name - Name of the graph to be created&lt;/li&gt;
&lt;li&gt;n - The number of nodes&lt;/li&gt;
&lt;li&gt;k - Each node is joined with its k nearest neighbors in a ring topology.&lt;/li&gt;
&lt;li&gt;p -The probability of rewiring each edge&lt;/li&gt;
&lt;li&gt;vertex_label_name - Name of the label to assign each vertex to.&lt;/li&gt;
&lt;li&gt;vertex_properties - Property values to assign each vertex. Default is NULL&lt;/li&gt;
&lt;li&gt;edge_label_name - Name of the label to assign each edge to.&lt;/li&gt;
&lt;li&gt;edge_properties - Property values to assign each edge. Default is NULL&lt;/li&gt;
&lt;li&gt;bidirectional - Bidirectional True or False. Default True.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM 
    age_create_watts_strogatz_graph('gp1', 8, 2, 0.5,
                                    'vertices',
                                    NULL,
                                    'edges',
                                    NULL,
                                    true);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query creates a graph named &lt;code&gt;gp1&lt;/code&gt; with 8 nodes. Each node is connected to its 2 nearest neighbors, and there is a 50% chance of rewiring each connection between two nodes. The node label is &lt;code&gt;vertices&lt;/code&gt;, and the edge label is &lt;code&gt;edges&lt;/code&gt;. Neither the vertices nor the edges have any properties, and the graph is bidirectional.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM 
    age_create_watts_strogatz_graph('gp2', 8, 5, 0.5, 
                                    'vertices',
                                    '{"type":"vertex"}',
                                    'edges',
                                    '{"type":"edge", "connection":"strong"}',
                                    false);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query creates a graph named &lt;code&gt;gp2&lt;/code&gt; with 8 nodes. Each node is connected to its 4 nearest neighbors, k-1 since k is odd, and there is a 50% chance of rewiring each connection between two nodes. The node label is &lt;code&gt;vertices&lt;/code&gt;, and the edge label is &lt;code&gt;edges&lt;/code&gt;. Each node has a property called &lt;code&gt;type&lt;/code&gt; and its value is &lt;code&gt;vertex&lt;/code&gt;. For the edges, there are 2 properties named &lt;code&gt;type&lt;/code&gt; and &lt;code&gt;cconnection&lt;/code&gt;, with the values &lt;code&gt;edge&lt;/code&gt; and &lt;code&gt;strong&lt;/code&gt;, respectively. This graph is not bidirectional.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When the functionality is merged into the source code, we will be able to create a Watts-Strogatz graph using the provided function and examples. This will enhance the graph generation algorithms in Apache AGE.&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>tutorial</category>
      <category>postgres</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Omega Strikers: Guide to Gear and Awakenings with Apache AGE</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Wed, 17 May 2023 21:50:30 +0000</pubDate>
      <link>https://dev.to/wendellana/omega-strikers-guide-to-gear-and-awakenings-with-apache-age-1o28</link>
      <guid>https://dev.to/wendellana/omega-strikers-guide-to-gear-and-awakenings-with-apache-age-1o28</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In today's article, I will begin by introducing Apache AGE and the game Omega Strikers. Following that, I will create a small graph to illustrate select data from the game. Finally, I will provide a conclusion summarizing the insights gained from this showcase.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Apache AGE&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Apache AGE is a PostgreSQL extension that provides graph database functionality. AGE is an acronym for A Graph Extension, and is inspired by Bitnine’s fork of PostgreSQL 10, AgensGraph, which is a multi-model database. The goal of the project is to create single storage that can handle both relational and graph model data so that users can use standard ANSI SQL along with openCypher, the Graph query language.&lt;br&gt;
Read more about Apache AGE here: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;&lt;br&gt;
Contribute to the Github repository: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Omega Strikers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Omega Strikers is a cross-platform game that offers an action-packed sports experience. In this game, you can play as a forward (also known as an attacker) or a goalie in a 3 versus 3 arena. The objective is to score goals while also trying to knock out your opponents. It is a free-to-play game available on PC, Nintendo Switch, PlayStation, Xbox, iOS, and Android platforms.&lt;br&gt;
In this game, players have the option to choose awakenings and gears that serve as special powers for their strikers (characters). In today's article, I will create two builds for the striker Juliette and present them in an Apache AGE graph format.&lt;/p&gt;

&lt;p&gt;There are more than 30 awakenings in the game, so I won't show them all. However, here you can see all the available gears in Omega Strikers, as there are only 8:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Advww-Aw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u00iykn82pgeordtz7p2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Advww-Aw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u00iykn82pgeordtz7p2.png" alt="All gears available in Omega Strikers" width="796" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Graph Creation and Visualization&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First and foremost, we need to create our graph. Let's name it &lt;code&gt;omega_strikers&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;SELECT create_graph('omega_strikers');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let's &lt;strong&gt;create our vertices&lt;/strong&gt;. First, the striker:&lt;br&gt;
&lt;code&gt;SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Striker)&lt;br&gt;
SET a.name = 'Juliette'&lt;br&gt;
$$) AS (a agtype);&lt;/code&gt;&lt;br&gt;
Next, the gear:&lt;br&gt;
&lt;code&gt;SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Gear {name: 'Magnetic Soles', description: 'Crossing midfield grants 30% speed for 1s'})&lt;br&gt;
$$) AS (a agtype);&lt;/code&gt;&lt;br&gt;
Moving on to the awakenings:&lt;br&gt;
&lt;code&gt;SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Awakening {name: 'One-Two Punch', description: 'Hit 25% harder (5% to core) against targets you\'ve hit within 2.5s'})&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Awakening {name: 'Built Different', description: 'Gain 40% size and your impact abilities hit 15% harder (3% to core)'})&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Awakening {name: 'Perfect Form', description: 'Hits reduce other ability cooldowns by 12% up to 1.2s per hit (4%/.4s for light hits)'})&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Awakening {name: 'Big Fish', description: 'Gain 40% size and 300 max stagger'})&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Awakening {name: 'Peak Performance', description: 'Gain 250 max stagger and 0.007% speed per 100 max stagger'})&lt;br&gt;
$$) AS (a agtype);&lt;/code&gt;&lt;br&gt;
Lastly, let's create the vertex for the build:&lt;br&gt;
&lt;code&gt;SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Build {name: 'Meta Forward'})&lt;br&gt;
$$) AS (a agtype);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let's &lt;strong&gt;create the relationships&lt;/strong&gt; by creating the edges:&lt;br&gt;
&lt;code&gt;SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
MATCH (n:Build), (m:Gear)&lt;br&gt;
CREATE (n)&amp;lt;-[a:Recommended]-(m)&lt;br&gt;
RETURN a&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
MATCH (n:Build), (m:Awakening)&lt;br&gt;
CREATE (n)&amp;lt;-[a:Recommended]-(m)&lt;br&gt;
RETURN a&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
MATCH (n:Build), (m:Striker)&lt;br&gt;
CREATE (n)-[a:Recommended]-&amp;gt;(m)&lt;br&gt;
RETURN a&lt;br&gt;
$$) AS (a agtype);&lt;/code&gt;&lt;br&gt;
Notice that we don't need to use the WHERE clause because we only have the gear, awakenings, striker, and build nodes that we want to create relationships with. Let's take a look at the graph:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rVfHY5PW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghwmzmhodg81rx9mynjw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rVfHY5PW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghwmzmhodg81rx9mynjw.png" alt="Graph visualization of the relationships with 1 striker, 1 build, 5 awakenings and 1 gear" width="800" height="336"&gt;&lt;/a&gt;&lt;br&gt;
Futhermore, we could add another build, for that we need to create some other vertices for awakenings and gear too. Here's the code:&lt;br&gt;
&lt;code&gt;SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Gear {name: 'Vicious Vambrace', description: 'Restore stagger equal to 25% of the damage you deal (reduced on core)'})&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Awakening {name: 'Bulk Up', description: 'Gain 250 max stagger and 1.5 power per 100 max stagger'})&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Awakening {name: 'Tempo Swing', description: 'Hitting anything heals you for 4% of your max stagger (1.33% for light hits) and deals that amount as damage to the target hit.'})&lt;br&gt;
$$) AS (a agtype);&lt;/code&gt;&lt;br&gt;
Next, we create the vertex for the &lt;code&gt;Tank/Bruiser Forward&lt;/code&gt; build and establish the corresponding edges:&lt;br&gt;
&lt;code&gt;SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
CREATE (a:Build {name: 'Tank/Bruiser Forward'})&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
MATCH (n:Build), (m:Gear)&lt;br&gt;
WHERE n.name = 'Tank/Bruiser Forward' AND m.name = 'Vicious Vambrace'&lt;br&gt;
CREATE (n)&amp;lt;-[a:Recommended]-(m)&lt;br&gt;
RETURN a&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
MATCH (n:Build), (m:Awakening)&lt;br&gt;
WHERE n.name = 'Tank/Bruiser Forward' AND (m.name = 'Big Fish' OR m.name='One-Two Punch' OR m.name = 'Bulk Up' OR m.name = 'Tempo Swing' OR m.name = 'Peak Performance')&lt;br&gt;
CREATE (n)&amp;lt;-[a:Recommended]-(m)&lt;br&gt;
RETURN a&lt;br&gt;
$$) AS (a agtype);&lt;br&gt;
SELECT * FROM cypher('omega_strikers', $$&lt;br&gt;
MATCH (n:Build), (m:Striker)&lt;br&gt;
WHERE n.name = 'Tank/Bruiser Forward' AND m.name = 'Juliette'&lt;br&gt;
CREATE (n)-[a:Recommended]-&amp;gt;(m)&lt;br&gt;
RETURN a&lt;br&gt;
$$) AS (a agtype);&lt;/code&gt;&lt;br&gt;
Now, let's take a look at how the graph looks like:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PeWMZpXs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gaugu77upbcgx3dhwwby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PeWMZpXs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gaugu77upbcgx3dhwwby.png" alt="Graph with 1 striker, 2 builds, 7 awakenings and 2 gears" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We can utilize Apache AGE for various purposes, such as analyzing data from a game. This includes examining insights like player counts, gaming hours, and other related factors if we had a larger database containing all the players' and matches' data.&lt;br&gt;
Additionally, we can explore, as we did, how the powers in the game, such as awakenings and gears, establish relationships with different types of builds (and possibily strikers). Apache AGE provides a versatile platform for conducting such analyses and gaining valuable insights.&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
      <category>omegastrikers</category>
      <category>learning</category>
    </item>
    <item>
      <title>Project: Label with a junction table and indexes</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Fri, 05 May 2023 18:38:43 +0000</pubDate>
      <link>https://dev.to/wendellana/solution-1-label-with-a-junction-table-and-indexes-2164</link>
      <guid>https://dev.to/wendellana/solution-1-label-with-a-junction-table-and-indexes-2164</guid>
      <description>&lt;p&gt;At present, Apache AGE does not support multiple labels in its vertices and edges. Furthermore, it utilizes the unique label identifier (ID) to create the unique identifier (ID) for the vertices and edges.&lt;br&gt;
My proposal here is to present a alternative solution for that problem and discuss any details. I'm open for feedbacks about it.&lt;br&gt;
Read about Apache AGE here: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;&lt;br&gt;
Github here: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution #1: Index for each label and a junction table
&lt;/h2&gt;

&lt;p&gt;My solution will use the power of indexing to fetch data quickly. The table &lt;code&gt;vertex&lt;/code&gt; will store a unique identifier (a simple sequential ID) and its properties as they exist today. The &lt;code&gt;edge&lt;/code&gt; will have the same fields, in addition to their &lt;code&gt;start_vertex&lt;/code&gt; and &lt;code&gt;end_vertex&lt;/code&gt;. This will look like the image provided here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UX8Q0WjT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7nqaxltaxs0yb03iafo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UX8Q0WjT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7nqaxltaxs0yb03iafo.png" alt="Image of the tables vertex and edge" width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going forward, I will use the terms 'node' and 'vertex' interchangeably. To store the label in the node or edge, I've considered using an array to store all labels or creating columns for each label. However, both of these solutions have their drawbacks. If we use an array to store the label references within the node and edge data, it will be difficult to efficiently query and update data. If we create a separate column in the node and edge table for each label, we may end up with a large number of columns, which can become difficult to manage and maintain as the number of labels grows. Additionally, adding or removing label would require modifying the node or edge table schema, which can be disruptive.&lt;/p&gt;

&lt;p&gt;Therefore, I propose another solution. We should create a table &lt;code&gt;label&lt;/code&gt;, that store the &lt;code&gt;label_id&lt;/code&gt; and &lt;code&gt;label_name&lt;/code&gt;, and a junction table &lt;code&gt;vertex_labels&lt;/code&gt; that links the table &lt;code&gt;vertex&lt;/code&gt; and the table &lt;code&gt;label&lt;/code&gt;. This junction table will have a composite primary key on the &lt;code&gt;vertex_id&lt;/code&gt; and &lt;code&gt;label_id&lt;/code&gt; columns, ensuring that it has no duplicates, and two foreign key columns: one that references the vertex table and one that references the label table. This allows a single node to have multiple label references, and the same solution applies to edges.&lt;br&gt;
Here is an example of how the tables would look like:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sd_7JrRn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whm0mab2tytai1946p6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sd_7JrRn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whm0mab2tytai1946p6w.png" alt="Table label with 3 rows: Movie, Actor and American. Table vertex_label linking the vertex 1 with the label Movie and American, and vertex 2 with label Actor and American" width="637" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, we will be using indexes, so we can create two indexes on the &lt;code&gt;node_labels&lt;/code&gt; table: one on the &lt;code&gt;label_id&lt;/code&gt; column, and another on the composite key of &lt;code&gt;node_id&lt;/code&gt; and &lt;code&gt;label_id&lt;/code&gt;. The first index allows us to quickly locate all nodes with a specific label, while the second index allows us to quickly locate all labels associated with a specific node.&lt;/p&gt;

&lt;p&gt;I think this is a simple solution, so it's feasible, and it solves both problems particularly well. &lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>database</category>
    </item>
    <item>
      <title>Apache AGE Setup for Contributing</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Wed, 26 Apr 2023 01:53:58 +0000</pubDate>
      <link>https://dev.to/wendellana/apache-age-setup-for-contributing-1hg5</link>
      <guid>https://dev.to/wendellana/apache-age-setup-for-contributing-1hg5</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this article, I will be discussing how to create a setup for contributing to the Apache AGE code. You must have a github account and PostgreSQL installed on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Tutorial&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The first step to setup AGE is to fork the Apache AGE repository on &lt;a href="https://github.com/apache/age"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XalN4y-N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/103xvhet3yq2sy58qnjh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XalN4y-N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/103xvhet3yq2sy58qnjh.png" alt="Fork button at Apache AGE repository on Github" width="800" height="40"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, clone the forked repository to your local machine using Git. You can run the following command in your terminal replacing &lt;code&gt;USER&lt;/code&gt; with your Github user:&lt;br&gt;
&lt;code&gt;git clone https://github.com/USER/apache-age.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add the path/to/postgres/include directory to your IDE environment's include path. This will ensure that the compiler recognizes dependencies such as &lt;code&gt;postgres.h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, you can begin making modifications to the code such as fixing issues and improving the performance of functions. After making the necessary changes, navigate to the folder where you cloned your forked repository and run the following commands:&lt;br&gt;
&lt;code&gt;make clean&lt;/code&gt;&lt;br&gt;
&lt;code&gt;make PG_CONFIG=/path/to/postgres/bin/pg_config install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For more details access &lt;a href="https://age.apache.org/contribution/how/"&gt;How to Contribute&lt;/a&gt; and the &lt;a href="https://age.apache.org/contribution/guide/"&gt;Contribution Guide&lt;/a&gt;&lt;br&gt;
Apache AGE repository: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;br&gt;
Apache AGE website: &lt;a href="https://age.apache.org"&gt;https://age.apache.org&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Apache AGE 1.3 Release for PostgreSQL 13</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Mon, 17 Apr 2023 23:19:32 +0000</pubDate>
      <link>https://dev.to/wendellana/apache-age-13-release-for-postgresql-13-4081</link>
      <guid>https://dev.to/wendellana/apache-age-13-release-for-postgresql-13-4081</guid>
      <description>&lt;p&gt;Apache AGE has released a new version that is compatible with PostgreSQL version 13. This is great news for developers as they can now take advantage of Postgres' 13 features and improvements in performance. Besides, this new release has added new features and enhancements to the Apache AGE too.&lt;/p&gt;

&lt;p&gt;Some of the key updates and fixes include the implementation of CALL ... [YIELD] for cypher functions, disallowing graph names with the empty string, and the optimization of the age_exists function. Additionally, there are fixes for various bugs related to clauses, commands, and labeling.&lt;/p&gt;

&lt;p&gt;The CALL clause is an essential feature in database programming, which allows programmers to invoke a deployed procedure within the database. Additionally, the YIELD sub-clause enables the selection of specific result fields that are to be returned as newly-bound variables from the procedure call. This provides users with greater flexibility and control over the returned data, allowing for further processing within the remaining query.&lt;/p&gt;

&lt;p&gt;I recommend taking a look at the full release notes for more detailed informations. Overall, this new version of Apache AGE should provide developers with improved functionality and performance.&lt;/p&gt;

&lt;p&gt;Apache AGE website: &lt;a href="https://age.apache.org"&gt;https://age.apache.org&lt;/a&gt;&lt;br&gt;
Apache AGE repository: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;br&gt;
Release branch: &lt;a href="https://github.com/apache/age/tree/release/PG13/1.3.0"&gt;https://github.com/apache/age/tree/release/PG13/1.3.0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
    </item>
    <item>
      <title>How the VLE Works - The Internals of Apache AGE</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Tue, 04 Apr 2023 19:11:44 +0000</pubDate>
      <link>https://dev.to/wendellana/how-the-vle-works-the-internals-of-apache-age-2mdk</link>
      <guid>https://dev.to/wendellana/how-the-vle-works-the-internals-of-apache-age-2mdk</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this article I will give an introduction to the internals of Apache AGE, specifically how the VLE (Variable Length Expressions) works.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A basic knowledge of PostgreSQL or any other Relational Database Management System (RDBMS), including an understanding of tables, schemas, and commonly used SQL queries such as SELECT, INSERT, DELETE, and UPDATE, is essential. Additionally, proficiency in JSON (JavaScript Object Notation) is also necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Variable-Length Expressions (VLE) Works&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;VLE allows users to express variable-length patterns in a graph, which can be useful for a wide range of applications, such as recommendation systems, fraud detection, and social network analysis.&lt;/p&gt;

&lt;p&gt;The VLE function in Apache AGE is responsible for loading the relevant parts of the graph into memory and executing the path-finding algorithm. This algorithm is a graph traversal algorithm that works on a graph, not a tree. It searches for all paths of any length from all vertices to all vertices, which can result in a high number of computations, especially for large graphs. The speed of the algorithm is directly related to the size and connectedness of the graph and what it is looking for.&lt;/p&gt;

&lt;p&gt;For instance, look at the following queries: &lt;br&gt;
&lt;code&gt;MATCH p=(u)-[*]-(v) RETURN p&lt;/code&gt;&lt;br&gt;
&lt;code&gt;MATCH (u)-[*]-(v) RETURN u&lt;/code&gt;&lt;br&gt;
&lt;code&gt;MATCH ()-[*]-() RETURN COUNT(1);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;All of these queries will basically do the same thing - search for all paths of any length from all vertices to all vertices. This means that for a graph of 1 million nodes, this algorithm will be invoked up to 1 trillion times (the number of VxV combinations). Now, add that you are asking for all of the paths between each combination. So, each additional path length can add to the work done.&lt;br&gt;
To minimize the workload, it is best to limit the algorithm's search scope by restricting where and how deeply it needs to look. This means restricting where it needs to look and how deeply it needs to look. Just because you restrict the input vertices doesn't mean that you restrict the interior vertices. The algorithm doesn't care about them, it only cares about interior edges.&lt;br&gt;
It is worth mentioning that the VLE function in Apache AGE generates all valid paths from a start vertex and leaves the match against the terminal vertex to Postgres, due to implementation factors.&lt;/p&gt;

&lt;p&gt;Apache AGE repository: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;br&gt;
Apache AGE website: &lt;a href="https://age.apache.org"&gt;https://age.apache.org&lt;/a&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>apacheage</category>
    </item>
    <item>
      <title>How the Cypher Command Works - The Internals of Apache AGE</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Fri, 31 Mar 2023 20:34:22 +0000</pubDate>
      <link>https://dev.to/wendellana/how-the-cypher-command-works-the-internals-of-apache-age-5dk8</link>
      <guid>https://dev.to/wendellana/how-the-cypher-command-works-the-internals-of-apache-age-5dk8</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this article I will give an introduction to the internals of Apache AGE, specifically about the Apache AGE architecture and how the Cypher command works.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A basic knowledge of PostgreSQL or any other Relational Database Management System (RDBMS), including an understanding of tables, schemas, and commonly used SQL queries such as SELECT, INSERT, DELETE, and UPDATE, is essential. Additionally, proficiency in JSON (JavaScript Object Notation) is also necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Apache AGE Architecture and How the Cypher Command Works&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenCypher is an open-source project that was initially developed by Neo4j to standardize the Cypher query language. Similar to SQL, openCypher is optimized for querying graph databases, providing a flexible and intuitive syntax for working with graph data.&lt;/p&gt;

&lt;p&gt;Although openCypher is largely based on Cypher, there are some differences between the two. For example, openCypher includes several new features and functions, such as support for path patterns, aggregation, and subqueries. &lt;/p&gt;

&lt;p&gt;To understand Apache AGE architecture, it is important to note that it is built on top of PostgreSQL and leverages hooks in PostgreSQL to modify certain processes. These hooks allow AGE to intercept queries and apply graph-specific processing to them, while still using the underlying PostgreSQL storage and indexing mechanisms. As a result, Apache AGE's architecture is very similar to PostgreSQL's, with some added components and functionality to support graph processing.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SD7lHFQ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9o5qgy1jdbectk9dc9f8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SD7lHFQ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9o5qgy1jdbectk9dc9f8.png" alt="Apache AGE Architecture" width="880" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Query Parsing: the query is broken down into its constituent parts and analyzed in order to determine how it should be executed. In the case of Apache AGE, the parsing process also includes additional steps than standard PostgreSQL to handle the graph queries. It converts the openCypher query into an internal graph query representation, which is then optimized and executed.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Query Transform: the query transformation process involves taking a high-level Cypher query and transforming it into a lower-level representation that can be executed efficiently on a graph database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Planner / Optimizer: it is responsible for generating an optimal query execution plan for a given openCypher query. The optimizer takes the input query and generates multiple candidate execution plans, each with a different set of operations and data access methods. The optimizer evaluates the candidate plans based on a set of cost metrics, such as execution time and resource usage, and selects the plan with the lowest overall cost.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Executor: it is responsible for executing the query plan generated by the query planner/optimizer. The executor receives the query plan and executes it against the underlying graph database. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transaction / Cache Layer: it is responsible for managing transactions in the graph database. The transaction cache layer is a key component of Apache AGE's architecture that enables fast and efficient transaction processing.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;PostgreSQL provides hooks that can be accessed after the Analyzer phase of its architecture, which Apache AGE leverages to intercept queries and apply graph-specific processing. However, because these hooks are not available during the parsing phase, AGE cannot directly support SQL being written in Cypher syntax.&lt;/p&gt;

&lt;p&gt;References&lt;br&gt;
&lt;a href="https://thestack.technology/what-is-apache-age/"&gt;https://thestack.technology/what-is-apache-age/&lt;/a&gt;. Accessed on 31/03/2023. &lt;/p&gt;

&lt;p&gt;Apache AGE repository: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;br&gt;
Apache AGE website: &lt;a href="https://age.apache.org"&gt;https://age.apache.org&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>apacheage</category>
      <category>postgres</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How Data is Stored - The Internals of Apache AGE</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Wed, 29 Mar 2023 22:34:06 +0000</pubDate>
      <link>https://dev.to/wendellana/how-data-is-stored-internals-of-apache-age-1d83</link>
      <guid>https://dev.to/wendellana/how-data-is-stored-internals-of-apache-age-1d83</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this article I will give an introduction to the internals of Apache AGE, specifically how data is stored in AGE. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A basic knowledge of PostgreSQL or any other Relational Database Management System (RDBMS), including an understanding of tables, schemas, and commonly used SQL queries such as SELECT, INSERT, DELETE, and UPDATE, is essential. Additionally, proficiency in JSON (JavaScript Object Notation) is also necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Data is Stored&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Apache AGE uses a separate namespace in PostgreSQL for each individual graph, with the data for each graph being stored in the table &lt;code&gt;ag_catalog.ag_graph&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nVNBsmaV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8f1fpgtwz9z71y02stvk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nVNBsmaV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8f1fpgtwz9z71y02stvk.png" alt="Executing SELECT oid, * FROM ag_catalog.ag_graph, showing all graphs" width="567" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;oid - PostgreSQL identifier for the graph&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;name - The graph name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;namespace - The schema name&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When creating a graph, it also creates two tables within this namespace:&lt;code&gt;_ag_label_vertex&lt;/code&gt; and &lt;code&gt;_ag_label_edge&lt;/code&gt;, these will be the parent tables of any new vertex or edge label you create. Vertices and edges in AGE are stored as rows in PostgreSQL tables, with each row representing a single vertex or edge in the graph.&lt;/p&gt;

&lt;p&gt;A label is generally a user-defined string that is assigned to vertices and edges in the graph to describe their type or category. The data for each label is stored in the table &lt;code&gt;ag_label&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YN0ou7nf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxcmm2nvwz22ep7kdmyn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YN0ou7nf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxcmm2nvwz22ep7kdmyn.png" alt="Executing SELECT oid, * FROM ag_catalog.ag_label, showing all labels" width="800" height="143"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;oid - Unique PostgreSQL identifier per label&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;name - The label name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;graph - The oid of the graph to which this label belongs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;id - The id for the label, unique per graph&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kind - The type of label as v stands for vertex and e for edge&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;relation - The schema-qualified table name for the label &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The data for all vertices and edges in a graph is stored at  &lt;code&gt;graph_name._ag_label_vertex&lt;/code&gt; and &lt;code&gt;graph_name._ag_label_edge&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y7BdFG1i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsfjel6hyjw9rhmo26op.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y7BdFG1i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsfjel6hyjw9rhmo26op.png" alt="SELECT on tables _ag_label_vertex and _ag_label_edge" width="800" height="194"&gt;&lt;/a&gt; It's possible to see the data for all vertices or edges under a specific label using &lt;code&gt;graph_name."Label"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Apache AGE repository: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;br&gt;
Apache AGE website: &lt;a href="https://age.apache.org"&gt;https://age.apache.org&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>apacheage</category>
      <category>postgres</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How Data is Represented - The Internals of Apache AGE</title>
      <dc:creator>Wendel Fernandes de Lana</dc:creator>
      <pubDate>Wed, 29 Mar 2023 21:35:02 +0000</pubDate>
      <link>https://dev.to/wendellana/how-is-data-represented-internals-of-apache-age-23jb</link>
      <guid>https://dev.to/wendellana/how-is-data-represented-internals-of-apache-age-23jb</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this article I will give an introduction to the internals of Apache AGE, specifically how data is represented in AGE. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A basic knowledge of PostgreSQL or any other Relational Database Management System (RDBMS), including an understanding of tables, schemas, and commonly used SQL queries such as SELECT, INSERT, DELETE, and UPDATE, is essential. Additionally, proficiency in JSON (JavaScript Object Notation) is also necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Data is Represented&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Apache AGE has extended PostgreSQL with a new data type called "agtype," which is based on PostgreSQL's JSONB implementation. The agtype data type provides support for three custom data types: vertices, edges, and paths, which enable graph database functionality within the PostgreSQL ecosystem.&lt;br&gt;
In AGE, data is represented using a graph model, which consists of vertices and edges. Vertices represent entities in the data, such as people, places, or things, and edges represent the relationships or connections between those entities. &lt;br&gt;
Each vertex and edge can have a set of properties, which are key-value pairs that provide additional information about the entity or relationship being represented. &lt;br&gt;
A path refers to a sequence of edges that connect two vertices in a graph, which may include zero or more edges and vertices, and it can be either directed or undirected.&lt;/p&gt;

&lt;p&gt;An agtype vertex consists of a graph ID, a label, and a set of properties&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
            "id": 844424930131969,&lt;br&gt;
            "label": "person",&lt;br&gt;
        "properties": {"key": "value"}&lt;br&gt;
}::vertex&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;An edge is defined by its graph ID, a label that describes its relationship to the vertices it connects, the graph IDs of its start and end vertices, and a set of properties&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
        "id": 1125899906842625,&lt;br&gt;
        "label": "reports_to", &lt;br&gt;
        "start_id": 844424930131969,&lt;br&gt;
        "end_id": 844424930131970,&lt;br&gt;
        "properties": {"key": "value"}&lt;br&gt;
}::edge&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A path is a list of alternating vertices and edges&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[vertex, edge, vertex, ...]::path&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Apache AGE repository: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;br&gt;
Apache AGE website: &lt;a href="https://age.apache.org"&gt;https://age.apache.org&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>apacheage</category>
      <category>postgres</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
