### Build and Install from Source Source: https://github.com/apache/age/blob/master/drivers/python/README.md Builds and installs the AGE Python driver locally from the source code using pip. ```bash pip install . ``` -------------------------------- ### Install AGE Dependencies on Ubuntu Source: https://github.com/apache/age/blob/master/README.md Installs essential libraries for building AGE from source on Ubuntu. ```bash sudo apt-get install build-essential libreadline-dev zlib1g-dev flex bison ``` -------------------------------- ### Install Apache AGE Extension Source: https://context7.com/apache/age/llms.txt Build and install the AGE extension from source. Ensure PostgreSQL development headers are installed. Alternatively, use Docker for a pre-built image. ```bash # Build and install the extension (requires PostgreSQL dev headers) sudo apt-get install build-essential libreadline-dev zlib1g-dev flex bison make install # or with explicit pg_config path: make PG_CONFIG=/path/to/postgres/bin/pg_config install ``` ```bash # Alternatively, run with Docker docker pull apache/age docker run --name age -p 5455:5432 \ -e POSTGRES_USER=postgresUser \ -e POSTGRES_PASSWORD=postgresPW \ -e POSTGRES_DB=postgresDB \ -d apache/age # Connect and bootstrap every new session docker exec -it age psql -d postgresDB -U postgresUser ``` -------------------------------- ### Install System Dependencies Source: https://github.com/apache/age/blob/master/drivers/python/README.md Installs necessary system packages for building the Python driver. Ensure you have root privileges. ```bash sudo apt-get update sudo apt-get install python3-dev libpq-dev git clone https://github.com/apache/age.git cd age/drivers/python ``` -------------------------------- ### Low-level Python Driver Setup Source: https://context7.com/apache/age/llms.txt Use `setUpAge` and `execCypher` from the `age.age` module for connection-pool or managed PostgreSQL scenarios where the high-level `Age` class is not suitable. ```python import psycopg from age.age import setUpAge, execCypher, deleteGraph ``` -------------------------------- ### Node.js Driver: setAGETypes and queryCypher Source: https://context7.com/apache/age/llms.txt This TypeScript example demonstrates registering the `agtype` parser and using helper functions for safe Cypher execution. Ensure the `pg` driver is installed. ```typescript import { Client } from 'pg'; import pgTypes from 'pg-types'; import { setAGETypes, queryCypher, createGraph, dropGraph } from 'pg-age'; async function main() { const client = new Client({ user: 'postgres', host: '127.0.0.1', database: 'mydb', password: 'secret', port: 5432, }); await client.connect(); // Register agtype parser; pass { createExtension: true } to auto-install await setAGETypes(client, pgTypes, { createExtension: true }); await createGraph(client, 'social'); // CREATE nodes using the cypher() wrapper await client.query(` SELECT * FROM cypher('social', $$ CREATE (:Person {name: 'Alice', age: 30}), (:Person {name: 'Bob', age: 25}) $$) AS (v agtype); `); // Use the safe queryCypher helper (validates graph name, dollar-quotes Cypher) const result = await queryCypher( client, 'social', 'MATCH (a:Person)-[r:KNOWS]->(b:Person) RETURN a, r, b', [{ name: 'a' }, { name: 'r' }, { name: 'b' }] ); for (const row of result.rows) { // row.a / row.r / row.b are parsed JS objects (via AGTypeParse) console.log(row.a, row.r, row.b); } await dropGraph(client, 'social', true); await client.end(); } main().catch(console.error); ``` -------------------------------- ### Install AGE Driver on Linux/OSX Source: https://github.com/apache/age/blob/master/drivers/golang/README.md Run the install script to set up the AGE driver on Linux and macOS systems. ```bash cd age/drivers/golang ./install.sh ``` -------------------------------- ### Install AGE Dependencies on Fedora Source: https://github.com/apache/age/blob/master/README.md Installs essential libraries for building AGE from source on Fedora. ```bash dnf install gcc glibc bison flex readline readline-devel zlib zlib-devel ``` -------------------------------- ### Install AGE Dependencies on CentOS Source: https://github.com/apache/age/blob/master/README.md Installs essential libraries for building AGE from source on CentOS. ```bash yum install gcc glibc glib-common readline readline-devel zlib zlib-devel flex bison ``` -------------------------------- ### Initialize AGE Connection and Graph Source: https://github.com/apache/age/blob/master/drivers/python/samples/networkx.ipynb Establishes a connection to the PostgreSQL database and sets up the AGE graph. Ensure you have psycopg and AGE installed. ```python import psycopg from age.networkx import * from age import * import networkx as nx conn = psycopg.connect( host="localhost", port="5432", dbname="postgres", user="moontasir", password="254826") graphName = 'bitnine_global_inic' age.setUpAge(conn, graphName) ``` -------------------------------- ### Install AGE Driver on Windows Source: https://github.com/apache/age/blob/master/drivers/golang/README.md Execute the batch script for installing the AGE driver on Windows. ```batch install.bat ``` -------------------------------- ### Run Golang Driver Tests Source: https://github.com/apache/age/blob/master/drivers/golang/README.md Navigate to the driver's test directory and execute tests using 'go test'. Ensure AGE is installed in your database and the DSN is correctly configured. ```bash cd age/drivers/golang/age go test . -v ``` -------------------------------- ### Java Example: Connect and Query AGE Graph Data Source: https://github.com/apache/age/blob/master/drivers/jdbc/README.md This Java code demonstrates connecting to a PostgreSQL database with the AGE extension, configuring AGE, executing a Cypher query, and retrieving results as Agtype objects. Ensure the AGE JDBC driver JAR is in your classpath and the AGE extension is installed on your database. ```java import org.apache.age.jdbc.base.Agtype; import org.postgresql.jdbc.PgConnection; import java.sql.*; public class Sample { static final String DB_URL = "jdbc:postgresql://localhost:5432/demo"; static final String USER = "postgres"; static final String PASS = "pass"; public static void main(String[] args) { // Open a connection try { PgConnection connection = DriverManager.getConnection(DB_URL, USER, PASS).unwrap(PgConnection.class); connection.addDataType("agtype", Agtype.class); // configure AGE Statement stmt = connection.createStatement(); stmt.execute("CREATE EXTENSION IF NOT EXISTS age;"); stmt.execute("LOAD 'age'"); stmt.execute("SET search_path = ag_catalog, \"$user\", public;"); // Run cypher ResultSet rs = stmt.executeQuery("SELECT * from cypher('demo_graph', $$ MATCH (n) RETURN n $$) as (n agtype);"); while (rs.next()) { // Returning Result as Agtype Agtype returnedAgtype = rs.getObject(1, Agtype.class); String nodeLabel = returnedAgtype.getMap().getObject("label").toString(); String nodeProp = returnedAgtype.getMap().getObject("properties").toString(); System.out.println("Vertex : " + nodeLabel + ", \tProps : " + nodeProp); } } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Install AGE with custom PostgreSQL path Source: https://github.com/apache/age/blob/master/README.md Installs the AGE extension when the PostgreSQL installation path is not in the system's PATH variable. Specify the correct path to pg_config. ```bash make PG_CONFIG=/path/to/postgres/bin/pg_config install ``` -------------------------------- ### Install PostgreSQL via apt Source: https://github.com/apache/age/blob/master/README.md Installs PostgreSQL using the apt package manager on Debian-based systems. Ensure you have the necessary permissions. ```bash sudo apt install postgresql ``` -------------------------------- ### Build and install AGE from source Source: https://github.com/apache/age/blob/master/README.md Compiles and installs the Apache AGE extension from its source code. This command should be run from the AGE source code directory. ```bash make install ``` -------------------------------- ### Install Python Requirements Source: https://github.com/apache/age/blob/master/drivers/python/README.md Installs the Python packages required by the AGE driver using pip. This should be run after cloning the repository. ```bash pip install -r requirements.txt ``` -------------------------------- ### Add AGE Driver Dependency with Go Get Source: https://github.com/apache/age/blob/master/drivers/golang/README.md Use 'go get' to fetch the Apache AGE Golang driver. ```bash go get github.com/apache/age/drivers/golang ``` -------------------------------- ### Hybrid SQL and Cypher Query Example Source: https://context7.com/apache/age/llms.txt Illustrates mixing standard SQL joins with openCypher MATCH patterns in a single query. This enables relational data to feed graph traversals. ```sql -- Find all Person nodes whose name appears in a relational table SELECT p.name, graph_result.* FROM my_users p, cypher('social', $$ MATCH (gp:Person {name: $name})-[:KNOWS*1..3]->(friend:Person) RETURN gp.name AS origin, friend.name AS friend_name $$, #vars) AS graph_result(origin agtype, friend_name agtype) WHERE p.active = true; -- Count graph hops alongside relational aggregates SELECT u.department, count(*) AS user_count, (SELECT count(*) FROM cypher('social', $$ MATCH (n:Person) WHERE n.dept = $dept RETURN n $$, #vars) AS (n agtype)) AS graph_nodes FROM my_users u GROUP BY u.department; ``` -------------------------------- ### Run AGE Docker container Source: https://github.com/apache/age/blob/master/README.md Creates and starts a new Docker container for Apache AGE. It maps the container's port 5432 to the host's 5455 and sets up environment variables for PostgreSQL. ```bash docker run \ --name age \ -p 5455:5432 \ -e POSTGRES_USER=postgresUser \ -e POSTGRES_PASSWORD=postgresPW \ -e POSTGRES_DB=postgresDB \ -d \ apache/age ``` -------------------------------- ### Non-Autocommit Client Pattern in Python Source: https://context7.com/apache/age/llms.txt Demonstrates how to handle AGE DDL-like operations in a non-autocommit client. Explicitly commit after setup for catalog writes to be visible. Alternatively, enable autocommit for immediate commits. ```python import psycopg params = dict(host='localhost', port=5432, user='postgres', password='secret', dbname='mydb') # ✅ Correct: commit() after setup so catalog writes are visible conn = psycopg.connect(**params) conn.execute("LOAD 'age'") conn.execute("SET search_path = ag_catalog, '$user', public") conn.commit() # closes the implicit outer transaction with conn.transaction(): conn.execute("SELECT create_graph('myapp')") # The graph is now committed and visible from new connections # ✅ Alternative: enable autocommit conn2 = psycopg.connect(**params, autocommit=True) conn2.execute("LOAD 'age'") conn2.execute("SET search_path = ag_catalog, '$user', public") conn2.execute("SELECT create_graph('myapp2')") # commits immediately conn2.close() ``` -------------------------------- ### Check PostgreSQL version with pg_config Source: https://github.com/apache/age/blob/master/README.md Verifies the installed PostgreSQL version. AGE currently supports PostgreSQL versions 11 through 18. ```bash pg_config ``` -------------------------------- ### Load AGE Extension in PostgreSQL Source: https://context7.com/apache/age/llms.txt Required SQL commands to load the AGE extension and set the search path at the start of every PostgreSQL connection. ```sql -- Required at the start of every connection CREATE EXTENSION age; LOAD 'age'; SET search_path = ag_catalog, "$user", public; ``` -------------------------------- ### Generate Agtype Parser with ANTLR4 Source: https://github.com/apache/age/blob/master/drivers/python/antlr/README.md Use this command to generate the Agtype parser. Ensure Java 8+ is installed and ANTLR4 JAR is downloaded. Specify the output directory and the grammar file. ```bash # prerequisites : # - java over 8 # - download ANTLR4 from https://www.antlr.org/download/antlr-4.11.1-complete.jar # - java -cp antlr-4.11.1-complete.jar org.antlr.v4.Tool -Dlanguage=Python3 -visitor -o ../age/gen ../../Agtype.g4 ``` -------------------------------- ### Executing Cypher Queries and Processing Paths in Python Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Shows how to execute a Cypher query to find paths and iterate through the results. Each row contains a path object, which can be indexed to access the start vertex, edge, and end vertex. ```python cursor = ag.execCypher("MATCH p=()-[:workWith]-() RETURN p") for row in cursor: path = row[0] print("START:", path[0]) print("EDGE:", path[1]) print("END:", path[2]) ``` -------------------------------- ### Create Relation with Multiple Columns Return Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Create a relation and return multiple columns (start vertex, edge, end vertex) with specified column aliases. Commit the transaction afterwards. ```python # With many columns Return cursor = ag.execCypher("""MATCH (a:Person {name: 'Joe'}), (b:Person {name: 'Jack'}) CREATE (a)-[r:workWith {weight: 5}]->(b) RETURN a, r, b """, cols=['a','r', 'b']) for row in cursor: print("(a)", row[0], ": (r)", row[1], ": (b)", row[2]) ag.commit() ``` -------------------------------- ### Java JDBC Driver: Agtype Result Parsing Source: https://context7.com/apache/age/llms.txt This Java example shows how to register the custom `Agtype` JDBC type to receive deserialized graph objects from Cypher queries. Ensure PostgreSQL JDBC driver is available. ```java import org.apache.age.jdbc.base.Agtype; import org.postgresql.jdbc.PgConnection; import java.sql.*; public class AgeExample { public static void main(String[] args) throws SQLException { PgConnection conn = DriverManager .getConnection("jdbc:postgresql://localhost:5432/mydb", "postgres", "secret") .unwrap(PgConnection.class); // Register the agtype → Agtype mapping conn.addDataType("agtype", Agtype.class); Statement stmt = conn.createStatement(); stmt.execute("CREATE EXTENSION IF NOT EXISTS age;"); stmt.execute("LOAD 'age'"); stmt.execute("SET search_path = ag_catalog, \"$user\", public;"); // Create graph and nodes stmt.execute("SELECT create_graph('demo_graph');"); stmt.execute("SELECT * FROM cypher('demo_graph', $$ " + "CREATE (:Person {name:'Alice', bornIn:'UK'}) $$) AS (a agtype);"); stmt.execute("SELECT * FROM cypher('demo_graph', $$ " + "CREATE (:Country {name:'UK'}) $$) AS (a agtype);"); stmt.execute("SELECT * FROM cypher('demo_graph', $$ " + "MATCH (p:Person),(c:Country) WHERE p.bornIn = c.name " + "CREATE (p)-[r:BORNIN]->(c) RETURN r $$) AS (r agtype);"); // Query results as Agtype objects ResultSet rs = stmt.executeQuery( "SELECT * FROM cypher('demo_graph', $$ MATCH (n) RETURN n $$) AS (n agtype);"); while (rs.next()) { Agtype agtype = rs.getObject(1, Agtype.class); String label = agtype.getMap().getObject("label").toString(); String props = agtype.getMap().getObject("properties").toString(); System.out.println("Label: " + label + " Props: " + props); } // Output: // Label: Person Props: {name=Alice, bornIn=UK} // Label: Country Props: {name=UK} // Drop graph with cascade stmt.execute("SELECT * FROM ag_catalog.drop_graph('demo_graph', true);"); conn.close(); } } ``` -------------------------------- ### setUpAge / execCypher (Python Driver - Low-level) Source: https://context7.com/apache/age/llms.txt Provides low-level functions like `setUpAge` and `execCypher` for scenarios requiring more control over connections, such as connection pooling or managed PostgreSQL environments. ```APIDOC ## setUpAge / Low-level execCypher (Python Driver) ### Description For connection-pool or managed PostgreSQL scenarios where the high-level `Age` class is not suitable, this module provides lower-level functions like `setUpAge` and `execCypher`. ### Method Python ### Endpoint N/A (Python Library) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python import psycopg from age.age import setUpAge, execCypher, deleteGraph # Example usage (details not fully provided in source) # conn = psycopg.connect(...) # setUpAge(conn) # execCypher(conn, "...") ``` ### Response #### Success Response (200) Functions operate on the provided connection object, executing queries and potentially modifying connection state. #### Response Example None provided in source. ``` -------------------------------- ### setUpAge with skip_load Source: https://github.com/apache/age/blob/master/drivers/python/README.md For connection pools managed externally, call `setUpAge()` with `skip_load=True` on each pooled connection to initialize AGE without attempting to load the extension. ```APIDOC ## setUpAge with skip_load ### Description For connection pools managed externally, call `setUpAge()` with `skip_load=True` on each pooled connection to initialize AGE without attempting to load the extension. ### Method `setUpAge()` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from age.age import setUpAge setUpAge(conn, 'graph_name', skip_load=True) ``` ### Response #### Success Response (200) None #### Response Example None ``` -------------------------------- ### Go Driver: GetReady and ExecCypher Source: https://context7.com/apache/age/llms.txt Use this for Go codebases managing their own `*sql.DB` pool and requiring fine-grained transaction control. `GetReady` loads AGE and creates the graph if absent. ```go package main import ( "database/sql" "fmt" "github.com/apache/age/drivers/golang/age" _ "github.com/lib/pq" ) func main() { db, _ := sql.Open("postgres", "host=127.0.0.1 port=5432 dbname=mydb user=postgres password=secret sslmode=disable") // GetReady loads AGE and creates the graph if absent age.GetReady(db, "social") tx, _ := db.Begin() // Create vertices age.ExecCypher(tx, "social", 0, "CREATE (n:Person {name: '%s', weight: %f})", "Joe", 67.3) age.ExecCypher(tx, "social", 0, "CREATE (n:Person {name: '%s', weight: %f})", "Jack", 77.3) tx.Commit() // Read back tx, _ = db.Begin() cur, _ := age.ExecCypher(tx, "social", 1, "MATCH (n:Person) RETURN n") for cur.Next() { row, _ := cur.GetRow() v := row[0].(*age.Vertex) fmt.Println(v.Id(), v.Label(), v.Props()) } tx.Commit() } ``` -------------------------------- ### Initialize AGE with Connection Pools Source: https://github.com/apache/age/blob/master/drivers/python/README.md When using external connection pools like `psycopg_pool.ConnectionPool`, call `setUpAge()` with `skip_load=True` on each pooled connection to initialize AGE without attempting to load the extension. ```python from age.age import setUpAge setUpAge(conn, 'graph_name', skip_load=True) ``` -------------------------------- ### Initialize AGE and Execute Cypher Queries (Python) Source: https://context7.com/apache/age/llms.txt Demonstrates connecting to an AGE graph, executing Cypher queries, and processing results. Use `skip_load=True` on Azure/AWS where AGE is preloaded server-side. Ensure `setUpAge` is called before executing queries. ```python import psycopg conn = psycopg.connect( host='myserver.postgres.database.azure.com', port=5432, user='dbuser', password='strong_password', dbname='mydb', autocommit=True ) setUpAge(conn, 'social', skip_load=True) # Execute a parameterised Cypher query cursor = execCypher(conn, 'social', "MATCH (p:Person) WHERE p.age > %s RETURN p", cols=['p'], params=(20,)) for row in cursor: vertex = row[0] # age.models.Vertex print(vertex.id, vertex.label, vertex.properties) # Output: 844424930131969 Person {'name': 'Alice', 'age': 30} # Clean up deleteGraph(conn, 'social') conn.close() ``` -------------------------------- ### Initialize PostgreSQL-AGE Connection Source: https://github.com/apache/age/blob/master/drivers/nodejs/README.md Connect to a PostgreSQL database and set up Apache AGE types for use with the client. Ensure the database configuration is correct. ```typescript import {types, Client, QueryResultRow} from "pg"; import {setAGETypes} from "../src"; const config = { user: 'postgres', host: '127.0.0.1', database: 'postgres', password: 'postgres', port: 25432, } const client = new Client(config); await client.connect(); await setAGETypes(client, types); await client.query(`SELECT create_graph('age-first-time');`); ``` -------------------------------- ### Connect and Execute Cypher Queries (Go) Source: https://context7.com/apache/age/llms.txt Illustrates using the Go driver to connect to an AGE graph, manage transactions, create vertices, and query results. The `ConnectAge` function initializes the extension and sets the search path. ```go package main import ( "fmt" "github.com/apache/age/drivers/golang/age" _ "github.com/lib/pq" ) func main() { dsn := "host=127.0.0.1 port=5432 dbname=mydb user=postgres password=secret sslmode=disable" // ConnectAge loads the extension, sets search_path, and creates the graph ag, err := age.ConnectAge("social", dsn) if err != nil { panic(err) } defer ag.Close() // Open a transaction tx, err := ag.Begin() if err != nil { panic(err) } // CREATE vertices (columnCount=0 means no RETURN) _, err = tx.ExecCypher(0, "CREATE (n:Person {name: '%s', age: %d})", "Alice", 30) if err != nil { panic(err) } _, err = tx.ExecCypher(0, "CREATE (n:Person {name: '%s', age: %d})", "Bob", 25) if err != nil { panic(err) } tx.Commit() // MATCH and read results (columnCount=1 → one return column) tx, _ = ag.Begin() cursor, err := tx.ExecCypher(1, "MATCH (n:Person) RETURN n") if err != nil { panic(err) } for cursor.Next() { row, _ := cursor.GetRow() v := row[0].(*age.Vertex) fmt.Printf("id=%d label=%s name=%v age=%v\n", v.Id(), v.Label(), v.Prop("name"), v.Prop("age")) } // Output: // id=844424930131969 label=Person name=Alice age=30 // id=844424930131970 label=Person name=Bob age=25 // Query a path (3 return columns: a, rel, b) cursor3, _ := tx.ExecCypher(3, "MATCH (a:Person)-[l:KNOWS]-(b:Person) RETURN a, l, b") for cursor3.Next() { row, _ := cursor3.GetRow() v1 := row[0].(*age.Vertex) edge := row[1].(*age.Edge) v2 := row[2].(*age.Vertex) fmt.Println(v1, edge.Props(), v2) } tx.Commit() } ``` -------------------------------- ### Query Relations with Multi-Column Return Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Query for relations and return the start vertex, edge label, and end vertex as separate columns. Access and print properties of the returned elements. ```python cursor = ag.execCypher("MATCH p=(a)-[b]-(c) RETURN a,label(b),c", cols=["a","b VARCHAR","c"]) for row in cursor: start = row[0] edge = row[1] end = row[2] print(start["name"] , edge.label, end["name"]) ``` -------------------------------- ### Build AGE JDBC Driver from Source Source: https://github.com/apache/age/blob/master/drivers/jdbc/README.md Clone the AGE repository, navigate to the JDBC driver directory, and run the Gradle assemble task to build the driver JAR file. ```bash git clone https://github.com/apache/age.git cd age/drivers/jdbc gradle assemble ``` -------------------------------- ### Working with Vertex, Edge, and Path Data Models (Python) Source: https://context7.com/apache/age/llms.txt Shows how to connect to an AGE graph, create nodes and edges, query paths, and access properties of `Vertex`, `Edge`, and `Path` objects. Results are automatically deserialized into typed Python objects. ```python import age ag = age.connect(graph='network', host='localhost', port=5432, user='postgres', password='secret', dbname='mydb') # Create a small graph ag.execCypher("CREATE (:Server {ip: '10.0.0.1', role: 'web'})") ag.execCypher("CREATE (:Server {ip: '10.0.0.2', role: 'db'})") ag.execCypher( "MATCH (a:Server {role:'web'}),(b:Server {role:'db'}) " "CREATE (a)-[:CONNECTS_TO {port: 5432}]->(b)" ) ag.commit() # Query a path cursor = ag.execCypher( "MATCH p=(a:Server)-[:CONNECTS_TO]->(b:Server) RETURN p", cols=['p'] ) for row in cursor: path = row[0] # age.models.Path src = path[0] # Vertex edge = path[1] # Edge dst = path[2] # Vertex print(f"Path length: {path.size()}") print(f" {src.properties['ip']} --[{edge.label} port={edge.properties['port']}]--> {dst.properties['ip']}") # Output: # Path length: 3 # 10.0.0.1 --[CONNECTS_TO port=5432]--> 10.0.0.2 ag.close() ``` -------------------------------- ### Create Relations with Parameters and Return Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Create relations using parameterized queries and return the created path. Ensure to commit the transaction after execution. ```python # With Params and Return cursor = ag.execCypher("""MATCH (a:Person), (b:Person) WHERE a.name = %s AND b.name = %s CREATE p=((a)-[r:workWith]->(b)) RETURN p""", params=('Andy', 'Smith',)) for row in cursor: print(row[0]) ag.commit() ``` -------------------------------- ### Accessing Edge Attributes in Python Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Demonstrates how to access attributes of an edge object, including its ID, label, start ID, end ID, and properties. Use this to inspect individual edge details. ```python edge = path.rel edge.id edge.label edge.start_id edge.end_id edge["property_name"] edge.properties ``` -------------------------------- ### AGE and NetworkX Integration (Python) Source: https://context7.com/apache/age/llms.txt Demonstrates converting an AGE graph to a NetworkX `DiGraph` for algorithm analysis and pushing a NetworkX graph into AGE. Requires `age.networkx` module. ```python import psycopg import networkx as nx from age.networkx import age_to_networkx, networkx_to_age conn = psycopg.connect(host='localhost', port=5432, user='postgres', password='secret', dbname='mydb') # --- AGE → NetworkX --- G = age_to_networkx(conn, graphName='social') print(nx.number_of_nodes(G), nx.number_of_edges(G)) # Run any NetworkX algorithm print(list(nx.pagerank(G).items())[:3]) # --- NetworkX → AGE --- H = nx.DiGraph() H.add_node(1, label='Device', properties={'type': 'router'}) H.add_node(2, label='Device', properties={'type': 'switch'}) H.add_edge(1, 2, label='LINKED', properties={'speed': '10G'}) networkx_to_age(conn, H, graphName='infra') conn.commit() conn.close() ``` -------------------------------- ### Import AGE Library Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Import the Apache AGE Python library to begin using its functionalities. ```python import age ``` -------------------------------- ### Create Nodes with Properties and an Edge Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-basic.ipynb Demonstrates creating multiple nodes with various data types, including a float, and then establishing a relationship between them. Note the handling of floating-point numbers in properties. ```python with conn.cursor() as cursor: try : cursor.execute("""SELECT * from cypher(%s, $$ CREATE (n:Person {name: 'Jack', title: 'Developer', score:-6.45161290322581e+46}) $$) as (v agtype); """, (GRAPH_NAME,) ) cursor.execute("""SELECT * from cypher(%s, $$ CREATE (n:Person {name: 'John', title: 'Developer'}) $$) as (v agtype); """, (GRAPH_NAME,)) cursor.execute("""SELECT * from cypher(%s, $$ MATCH (a:Person {name: 'Jack'}), (b:Person {name: 'John'}) CREATE (a)-[r:workWith {weight: 2}]->(b) $$) as (v agtype); """, (GRAPH_NAME,)) ``` -------------------------------- ### Creating and Changing Vertices Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Demonstrates how to create and modify vertices using `execCypher`. Highlights the importance of the `commit` parameter and explicit transaction commits. ```APIDOC ## Create & Change Vertices using execCypher ### Description Use `execCypher` to create, set properties, or remove vertices. The `commit` parameter controls automatic transaction handling. ### Usage - `ag.execCypher(cypherStmt, commit=False)`: Executes the statement, returns a cursor for results, requires explicit `ag.commit()`. - `ag.execCypher(cypherStmt, commit=True)`: Executes and commits automatically, cursor is closed. ### Example (Create Vertex with Properties) ```python ag.execCypher("CREATE (n:Person {name: %s}) RETURN n", params=('Jack',)) ``` ### Example (Set Property) ```python ag.execCypher("MATCH (n:Person {name: %s}) SET n.title=%s RETURN n.title", cols=["a VARCHAR"], params=('Smith','Manager',)) ``` ### Example (Remove Property) ```python ag.execCypher("MATCH (n:Person {name: %s}) REMOVE n.title RETURN id(n)", cols=["a BIGINT"], params=('Smith',)) ``` ### Transaction Commit ```python # After operations with commit=False, commit explicitly ag.commit() ``` ``` -------------------------------- ### Fix 1: Explicit Commit for psycopg v3 Graph Creation Source: https://github.com/apache/age/blob/master/README.md Solves the savepoint issue by explicitly calling `conn.commit()` after initial setup, closing the implicit outer transaction. The subsequent `with conn.transaction():` block then becomes a top-level transaction that commits on exit. ```python conn = psycopg.connect(**params) conn.execute("LOAD 'age'") conn.execute("SET search_path = ag_catalog, '$user', public") conn.commit() # <-- closes the implicit outer txn with conn.transaction(), conn.cursor() as cur: cur.execute("SELECT * FROM create_graph('my_graph')") # this transaction block is now top-level and commits on exit conn.close() ``` -------------------------------- ### Create Another Vertex with Label and Properties Source: https://github.com/apache/age/blob/master/README.md This snippet demonstrates creating a second vertex, similar to the previous one, which can then be used for creating edges. ```bash SELECT * FROM cypher('graph_name', $$ CREATE (:label {property:"Node B"}) $$) as (v agtype); ``` -------------------------------- ### Querying Paths with Multiple Columns and Parameters in Python Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Demonstrates how to execute a Cypher query that returns multiple columns, including vertex properties and edge attributes, with parameterization. Use this for more complex data retrieval and filtering. ```python cursor = ag.execCypher("MATCH p=(a)-[b]-(c) WHERE b.weight>%s RETURN a,label(b), b.weight, c", cols=["a","bl","bw", "c"], params=(2,)) for row in cursor: start = row[0] edgel = row[1] edgew = row[2] end = row[3] print(start["name"] , edgel, edgew, end["name"]) ``` -------------------------------- ### Run Networkx Unit Test Source: https://github.com/apache/age/blob/master/drivers/python/README.md Execute Networkx unit tests for Apache AGE. Specify connection parameters such as host, database, user, password, and port. ```bash python test_networkx.py \ -host "127.0.0.1" \ -db "postgres" \ -u "postgres" \ -pass "agens" \ -port 5432 ``` -------------------------------- ### Connect with Non-Superuser Privileges Source: https://github.com/apache/age/blob/master/drivers/python/README.md Use `load_from_plugins=True` to load the AGE extension from the PostgreSQL plugins directory for non-superuser accounts. Ensure the non-superuser has proper permissions on graph schemas and objects. ```python ag = age.connect(host='localhost', port=5432, user='dbuser', password='strong_password', dbname='postgres', load_from_plugins=True, graph='graph_name') ``` -------------------------------- ### Connecting to PostgreSQL with AGE Extension Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Establishes a connection to a PostgreSQL server and loads the AGE extension. Supports connection via DSN string or individual parameters. Automatically creates the graph if it doesn't exist. ```APIDOC ## age.connect ### Description Connect PostgreSQL server and load AGE extension. ### Parameters - **graph** (str, optional): The name of the graph to connect to. If not provided, a graph can be set later using `setGraph`. - **dsn** (str, optional): A Data Source Name string for connecting to PostgreSQL. - **connection_factory** (callable, optional): A factory for creating connections. - **cursor_factory** (callable, optional): A factory for creating cursors. - **kwargs**: Additional keyword arguments for connection, such as host, port, dbname, user, password. ### Returns - **Age**: An Age object representing the connection to the graph database. ``` -------------------------------- ### Create Vertex with Label and Properties Source: https://github.com/apache/age/blob/master/README.md Use the `CREATE` clause within a `cypher` query to create a vertex with a specified label and properties. Ensure the graph exists before running this. ```bash SELECT * FROM cypher('graph_name', $$ CREATE (:label {property:"Node A"}) $$) as (v agtype); ``` -------------------------------- ### Querying Vertices Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Shows how to query vertices using `execCypher` and access the returned data. ```APIDOC ## Query Vertices using execCypher ### Description Execute Cypher statements to query vertices and retrieve results using `execCypher`. ### Method Signature `execCypher(cypherStmt:str, cols:list=None, params:tuple=None)` ### Example (Querying a Vertex) ```python cursor = ag.execCypher("MATCH (n:Person {name: %s}) RETURN n", params=('Andy',)) for row in cursor: vertex = row[0] print(vertex.id, vertex["name"], vertex) # Access id, label, properties ``` ``` -------------------------------- ### Connect and Execute Cypher with Python Driver Source: https://context7.com/apache/age/llms.txt Use the `apache-age-python` package to connect to AGE and execute Cypher queries. The `Age` object wraps psycopg3 and handles `agtype` loading. ```python import age # Connect and auto-create the graph if it does not exist ag = age.connect( graph='social', host='localhost', port=5432, user='postgres', password='secret', dbname='mydb' ) # CREATE nodes ag.execCypher("CREATE (:Person {name: %s, age: %s})", params=('Alice', 30)) ag.execCypher("CREATE (:Person {name: %s, age: %s})", params=('Bob', 25)) ag.commit() # CREATE relationship ag.execCypher( "MATCH (a:Person {name: %s}), (b:Person {name: %s}) " "CREATE (a)-[r:KNOWS {since: 2020}]->(b)", params=('Alice', 'Bob') ) ag.commit() # MATCH and iterate results — cols maps return columns to agtype aliases cursor = ag.execCypher( "MATCH (a:Person)-[r:KNOWS]->(b:Person) RETURN a, r, b", cols=['a', 'r', 'b'] ) for row in cursor: person_a = row[0] # age.models.Vertex rel = row[1] # age.models.Edge person_b = row[2] # age.models.Vertex print(f"{person_a.properties['name']} --[{rel.label}]--> {person_b.properties['name']}") # Output: Alice --[KNOWS]--> Bob ag.close() ``` -------------------------------- ### Connect to PostgreSQL and AGE Graph Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-basic.ipynb Establishes a connection to a PostgreSQL database and specifies the graph name for AGE operations. Ensure the database and graph exist before connecting. ```python import psycopg import age GRAPH_NAME = "test_graph" ag = age.connect(host="172.17.0.2", port="5432", dbname="postgre", user="postgres", password="agens", graph=GRAPH_NAME) conn = ag.connection ``` -------------------------------- ### age.connect / age.execCypher (Python Driver) Source: https://context7.com/apache/age/llms.txt Connects to a specified graph and executes openCypher queries using the high-level `Age` object. Supports parameter binding and returns results parsed into native Python objects. ```APIDOC ## age.connect / age.execCypher (Python Driver) ### Description The `apache-age-python` package wraps psycopg3 to register the `agtype` loader and expose a high-level `Age` object for interacting with AGE graphs. ### Method Python ### Endpoint N/A (Python Library) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python import age # Connect and auto-create the graph if it does not exist ag = age.connect( graph='social', host='localhost', port=5432, user='postgres', password='secret', dbname='mydb' ) # CREATE nodes ag.execCypher("CREATE (:Person {name: %s, age: %s})", params=('Alice', 30)) ag.execCypher("CREATE (:Person {name: %s, age: %s})", params=('Bob', 25)) ag.commit() # CREATE relationship ag.execCypher( "MATCH (a:Person {name: %s}), (b:Person {name: %s}) " "CREATE (a)-[r:KNOWS {since: 2020}]->(b)", params=('Alice', 'Bob') ) ag.commit() ``` ### Response #### Success Response (200) Returns results from `execCypher` as an iterable cursor. Each row contains parsed `agtype` objects (Vertex, Edge, Path). #### Response Example ```python # MATCH and iterate results — cols maps return columns to agtype aliases cursor = ag.execCypher( "MATCH (a:Person)-[r:KNOWS]->(b:Person) RETURN a, r, b", cols=['a', 'r', 'b'] ) for row in cursor: person_a = row[0] # age.models.Vertex rel = row[1] # age.models.Edge person_b = row[2] # age.models.Vertex print(f"{person_a.properties['name']} --[{rel.label}]--> {person_b.properties['name']}") # Output: Alice --[KNOWS]--> Bob ag.close() ``` ``` -------------------------------- ### Enable Apache AGE Extension in PostgreSQL Source: https://github.com/apache/age/blob/master/drivers/golang/README.md Connect to your PostgreSQL instance and execute these SQL commands to load the AGE extension. ```sql # psql CREATE EXTENSION age; LOAD 'age'; SET search_path = ag_catalog, "$user", public; ``` -------------------------------- ### Connecting with load_from_plugins Source: https://github.com/apache/age/blob/master/drivers/python/README.md Connect to Apache AGE using the `load_from_plugins` parameter for non-superuser usage. This attempts to load the AGE extension from the PostgreSQL plugins directory. ```APIDOC ## Connecting with load_from_plugins ### Description Connect to Apache AGE using the `load_from_plugins` parameter for non-superuser usage. This attempts to load the AGE extension from the PostgreSQL plugins directory. ### Method `age.connect()` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python import age ag = age.connect(host='localhost', port=5432, user='dbuser', password='strong_password', dbname='postgres', load_from_plugins=True, graph='graph_name') ``` ### Response #### Success Response (200) Connection object #### Response Example None ``` -------------------------------- ### Run Integration Tests Source: https://github.com/apache/age/blob/master/drivers/python/README.md Executes integration tests for the AGE Python driver. Provide connection details and graph name as arguments. ```bash python test_age_py.py \ -host "127.0.0.1" \ -db "postgres" \ -u "postgres" \ -pass "agens" \ -port 5432 \ -gn "test_graph" ``` -------------------------------- ### Connect to PostgreSQL with AGE Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Connect to a PostgreSQL server and load the AGE extension. This can be done using a graph name or without one, allowing for graph creation later. Transactions must be explicitly committed or rolled back. ```python ag = age.connect(graph="(graph name}", host="{host}", port="{port}", dbname="{dbname}", user="{db username}", password="{password}") ``` ```python DSN = "host={host} port={port} dbname={dbname} user={db username} password={password}" ag = age.connect(graph="(graph name}", dsn=DSN) ``` ```python # or Without Graph Name : you can make a new graph later. ag = age.connect(host="{host}", port="{port}", dbname="{dbname}", user="{db username}", password="{password}") ``` ```python # And set graph - if you don't have one yet, setGraph make that.) ag = age.setGraph("{graph name}") ``` -------------------------------- ### Create Relations (Multiple) Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Create multiple relations between vertices, some with specified weights. Ensure to commit the transaction after creating the relations. ```python # Create Edges ag.execCypher("MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Smith' CREATE (a)-[r:workWith {weight: 3}]->(b)") ag.execCypher("MATCH (a:Person), (b:Person) WHERE a.name = 'Andy' AND b.name = 'Tom' CREATE (a)-[r:workWith {weight: 1}]->(b)") ag.execCypher("MATCH (a:Person {name: 'Jack'}), (b:Person {name: 'Andy'}) CREATE (a)-[r:workWith {weight: 5}]->(b)") ag.commit() ``` -------------------------------- ### Run Unit Tests Source: https://github.com/apache/age/blob/master/drivers/python/README.md Executes unit tests for the AGE Python driver using the unittest module. Use the -v flag for verbose output. ```bash python -m unittest -v test_agtypes.py ``` -------------------------------- ### Create Nodes and Edges in a Transaction Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Demonstrates creating multiple nodes and edges within explicit transaction blocks. Ensure to commit explicitly after all executions or rollback on exception. ```python with ag.connection.cursor() as cursor: try : ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('USA',)) ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('France',)) ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('Korea',)) ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('Russia',)) # You must commit explicitly after all executions. ag.connection.commit() except Exception as ex: ag.rollback() raise ex with ag.connection.cursor() as cursor: try :# Create Edges ag.cypher(cursor,"MATCH (a:Country), (b:Country) WHERE a.name = 'USA' AND b.name = 'France' CREATE (a)-[r:distance {unit:'miles', value: 4760}]->(b)") ag.cypher(cursor,"MATCH (a:Country), (b:Country) WHERE a.name = 'France' AND b.name = 'Korea' CREATE (a)-[r:distance {unit: 'km', value: 9228}]->(b)") ag.cypher(cursor,"MATCH (a:Country {name: 'Korea'}), (b:Country {name: 'Russia'}) CREATE (a)-[r:distance {unit:'km', value: 3078}]->(b)") # You must commit explicitly ag.connection.commit() except Exception as ex: ag.rollback() raise ex ``` -------------------------------- ### Create Vertices with AGE Source: https://github.com/apache/age/blob/master/drivers/python/samples/apache-age-note.ipynb Create new vertices in the graph. Use `execCypher` with `commit=False` to access results and then explicitly call `ag.commit()`. Alternatively, `commit=True` executes and commits automatically but closes the cursor. ```python cursor = ag.execCypher("CREATE(...)", commit=False) # Cypher Create Statement ... # check result in cursor ... ag.commit() # commit explicitly ``` ```python # Create Vertices ag.execCypher("CREATE (n:Person {name: 'Joe'})") ag.execCypher("CREATE (n:Person {name: 'Smith'})") ``` ```python # Execution with one agtype result cursor = ag.execCypher("CREATE (n:Person {name: %s}) RETURN n", params=('Jack',)) for row in cursor: print("CREATED: ", row[0]) ``` ```python cursor = ag.execCypher("CREATE (n:Person {name: %s, title: 'Developer'}) RETURN id(n)", params=('Andy',)) for row in cursor: print("CREATED: ", row[0]) ``` ```python # Execution with one result as SQL TYPE cursor = ag.execCypher("MATCH (n:Person {name: %s}) SET n.title=%s RETURN n.title", cols=["a VARCHAR"], params=('Smith','Manager',)) for row in cursor: print("SET: ", row[0]) ``` ```python # Execution with one result as SQL TYPE cursor = ag.execCypher("MATCH (n:Person {name: %s}) REMOVE n.title RETURN id(n)", cols=["a BIGINT"], params=('Smith',)) for row in cursor: print("REMOVE Prop: ", row[0]) ``` ```python # You must commit explicitly ag.commit() ```