├── Dockerfile └── README.md /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:11 2 | 3 | RUN apt-get update 4 | RUN apt-get install --assume-yes --no-install-recommends --no-install-suggests \ 5 | bison \ 6 | build-essential \ 7 | ca-certificates \ 8 | flex \ 9 | git \ 10 | postgresql-plpython3-11 \ 11 | postgresql-server-dev-11 12 | 13 | RUN git clone https://github.com/apache/incubator-age /age 14 | 15 | RUN cd /age && \ 16 | git checkout tags/v.0.7.0-rc0 && \ 17 | make install 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker Apache AGE for Postgres 2 | 3 | This is an image to build the [Apache AGE](https://github.com/apache/incubator-age/) on the official PostgreSQL 11 Docker image. It can be run by executing 4 | 5 | ## Running the container 6 | 7 | It can be run by executing: 8 | 9 | `docker run -it -e POSTGRES_PASSWORD=mypassword -p {HostPort}:5432 sorrell/apache-age` 10 | 11 | In the above command, replace `{HostPort}` with a port you'd like to forward to, or remove the `-p` flag altogether if you want to run `psql` from inside the container. 12 | 13 | ## Loading AGE 14 | 15 | Connect to your containerized Postgres instance, for example: 16 | 17 | ```sh 18 | psql -h 0.0.0.0 -p {HostPort} -U postgres 19 | ``` 20 | 21 | Then run the following commands: 22 | 23 | ```sql 24 | CREATE EXTENSION age; 25 | LOAD 'age'; 26 | SET search_path = ag_catalog, "$user", public; 27 | ``` 28 | 29 | ## Using AGE 30 | 31 | First you will need to create a graph: 32 | 33 | ```sql 34 | SELECT create_graph('my_graph_name'); 35 | ``` 36 | 37 | To execute Cypher queries, you will need to wrap them in the following syntax: 38 | 39 | ```sql 40 | SELECT * from cypher('my_graph_name', $$ 41 | CypherQuery 42 | $$) as (a agtype); 43 | ``` 44 | 45 | For example, if we wanted to create a graph with 4 nodes, we could do something as shown below: 46 | 47 | ```sql 48 | SELECT * from cypher('my_graph_name', $$ 49 | CREATE (a:Part {part_num: '123'}), 50 | (b:Part {part_num: '345'}), 51 | (c:Part {part_num: '456'}), 52 | (d:Part {part_num: '789'}) 53 | $$) as (a agtype); 54 | 55 | --- RESULTS 56 | a 57 | --- 58 | (0 rows) 59 | ``` 60 | 61 | Then we could query the graph with the following: 62 | 63 | ```sql 64 | SELECT * from cypher('my_graph_name', $$ 65 | MATCH (a) 66 | RETURN a 67 | $$) as (a agtype); 68 | 69 | --- RESULTS 70 | a 71 | ------------------------------------------------------------------------------------- 72 | {"id": 844424930131969, "label": "Part", "properties": {"part_num": "123"}}::vertex 73 | {"id": 844424930131970, "label": "Part", "properties": {"part_num": "345"}}::vertex 74 | {"id": 844424930131971, "label": "Part", "properties": {"part_num": "456"}}::vertex 75 | {"id": 844424930131972, "label": "Part", "properties": {"part_num": "789"}}::vertex 76 | (4 rows) 77 | ``` 78 | 79 | Next, we could create a relationship between a couple of nodes: 80 | 81 | ```sql 82 | SELECT * from cypher('my_graph_name', $$ 83 | MATCH (a:Part {part_num: '123'}), (b:Part {part_num: '345'}) 84 | CREATE (a)-[u:used_by { quantity: 1 }]->(b) 85 | $$) as (a agtype); 86 | 87 | --- RESULTS 88 | a 89 | --- 90 | (0 rows) 91 | ``` 92 | 93 | Next we can return the path we just created (results have been formatted for readability): 94 | 95 | ```sql 96 | SELECT * from cypher('my_graph_name', $$ 97 | MATCH p=(a)-[]-(b) 98 | RETURN p 99 | $$) as (a agtype); 100 | ``` 101 | 102 | ```javascript 103 | // RESULTS 104 | // ROW 1 105 | [ 106 | { 107 | "id":844424930131969, 108 | "label":"Part", 109 | "properties":{ 110 | "part_num":"123" 111 | } 112 | }::"vertex", 113 | { 114 | "id":1125899906842625, 115 | "label":"used_by", 116 | "end_id":844424930131970, 117 | "start_id":844424930131969, 118 | "properties":{ 119 | "quantity":1 120 | } 121 | }::"edge", 122 | { 123 | "id":844424930131970, 124 | "label":"Part", 125 | "properties":{ 126 | "part_num":"345" 127 | } 128 | }::"vertex" 129 | ]::"path" 130 | // ROW 2 131 | [ 132 | { 133 | "id":844424930131970, 134 | "label":"Part", 135 | "properties":{ 136 | "part_num":"345" 137 | } 138 | }::"vertex", 139 | { 140 | "id":1125899906842625, 141 | "label":"used_by", 142 | "end_id":844424930131970, 143 | "start_id":844424930131969, 144 | "properties":{ 145 | "quantity":1 146 | } 147 | }::"edge", 148 | { 149 | "id":844424930131969, 150 | "label":"Part", 151 | "properties":{ 152 | "part_num":"123" 153 | } 154 | }::"vertex" 155 | ]::"path" 156 | (2 rows) 157 | ``` 158 | --------------------------------------------------------------------------------