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

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_file and load_edges_from_file functions 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:

    sql
    CREATE 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 example SELECT * FROM cypher('hop_graph', MATCH (n) RETURN count(n) ) AS (c agtype); after LOAD 'age'; SET search_path = ag_catalog, "$user", public;.