Apache AGE
Description
Apache AGE is a PostgreSQL extension which adds graphs, queried with Cypher, to PostgreSQL. Hop connects to it through the PostgreSQL JDBC driver which comes with Hop, with a graph database connection of the Apache AGE type, from the optional Apache AGE plugin.
A connection works with one graph: the graph name is one of its options, and Hop can create the graph when it doesn’t exist.
Hop loads the AGE extension in every connection, so there is no need to set shared_preload_libraries for Hop.
Run Apache AGE in docker
docker run -p 5432:5432 -e POSTGRES_USER=hop -e POSTGRES_PASSWORD=hop -e POSTGRES_DB=hop apache/age
What works
-
Graph query, including Return graph
-
Graph output, including the validation against the graph model and its indexes
-
The Graph index action, for named indexes on node properties: it creates PostgreSQL indexes, see below.
-
Execution logging (
HOP_GRAPH_LOGGING_CONNECTION), the Get graph logging info transform and the Graph logging perspective -
The graph database location for execution information
What doesn’t work
-
The Graph constraint action, and the Graph index action for vector indexes and indexes on relationship properties: AGE indexes and constraints are PostgreSQL indexes and constraints.
-
Create indexes in Graph output and Cypher output, for the same reason.
-
RETURN *and statements which return unnamed values. -
Nodes with more than one label, and labels with spaces.
-
Neo4j import: load the files of Generate graph CSVs with plain column names with the
load_labels_from_fileandload_edges_from_filefunctions of AGE instead.
Differences with Neo4j
-
Statements which return values need to name them, for example
RETURN n.name AS name: AGE needs to know how many values come back.RETURN *isn’t supported. -
A node has one label, and label names can’t contain spaces. Graph names have at least 3 characters.
-
AGE has no temporal types: dates and times are stored as ISO strings.
-
Indexes are PostgreSQL indexes on the tables AGE keeps per label, created with SQL. The Graph index action creates them on node properties, and creates the label first when it has no nodes yet. The Show indexes DDL button of the graph database location gives the SQL for its indexes, for example:
sqlCREATE INDEX IF NOT EXISTS "idx_execution_id" ON "hop_graph"."Execution" (ag_catalog.agtype_access_operator(VARIADIC ARRAY[properties, '"id"'::ag_catalog.agtype]))Graph output validation against a graph model takes these indexes into account.
-
There is no browser in the AGE image itself: query the graph with
psql, for exampleSELECT * FROM cypher('hop_graph', MATCH (n) RETURN count(n) ) AS (c agtype);afterLOAD 'age'; SET search_path = ag_catalog, "$user", public;.