Graph Query¶
This section describes how to run graph queries in AkasicDB.
Prepare the Graph¶
For instructions on preparing the tables, see Prepare Tables.
-- Define a graph named 'retail_graph'
SELECT akasicdb.define_graph('retail_graph');
-- Add vertex definitions named 'v_item', 'v_customer', and 'v_store'
-- to the 'retail_graph' graph definition
SELECT akasicdb.define_vertex(
'retail_graph',
'v_item',
ARRAY['i_no integer', 'name varchar(50)', 'price decimal(7,2)'],
'item'
);
SELECT akasicdb.define_vertex(
'retail_graph',
'v_customer',
ARRAY['c_id integer', 'first_name varchar(20)', 'last_name varchar(30)'],
'customer'
);
SELECT akasicdb.define_vertex(
'retail_graph',
'v_store',
ARRAY['s_id integer', 'name varchar(50)'],
'store',
'SELECT s_id, name FROM store'
);
-- Add edge definitions named 'buy' and 'sell'
-- to the 'retail_graph' graph definition
SELECT akasicdb.define_edge(
'retail_graph',
'buy',
'v_customer', 'v_item',
null,
'SELECT null FROM customer c, orders o, item i '
'WHERE c.c_id = o.c_id AND i.i_no = o.i_no',
'customer c', 'item i'
);
SELECT akasicdb.define_edge(
'retail_graph',
'sell',
'v_store', 'v_item',
null,
'SELECT null FROM store s, orders o, item i '
'WHERE s.s_id = o.s_id AND i.i_no = o.i_no',
'store s', 'item i'
);
-- Add an edge definition named 'co_purchase'
-- to the 'retail_graph' graph definition
SELECT akasicdb.define_edge(
'retail_graph',
'co_purchase',
'v_customer', 'v_customer',
null,
'SELECT null '
'FROM customer c1, orders o1, item i, orders o2, customer c2 '
'WHERE c1.c_id = o1.c_id AND i.i_no = o1.i_no '
'AND c2.c_id = o2.c_id AND i.i_no = o2.i_no',
'customer c1', 'customer c2'
);
-- Create a graph based on the 'retail_graph' graph definition
SELECT akasicdb.create_graph('retail_graph');
SQL/GQL Query Interface¶
What is SQL/GQL?¶
SQL/GQL is AkasicDB’s query language for graph, vector, and relational data. The akasicdb.cypher() function allows you to run GQL, the ISO-standard graph query language. You can also post-process graph query results as relational tables or combine them with other SQL queries. The vector operators described in Vector Features - Querying can also be used directly in GQL queries.
Function arguments
Basic usage of akasicdb.cypher():
akasicdb.cypher(
graph_name NAME, -- Name of the graph to query
query_string TEXT -- Graph query to execute
);
akasicdb.cypher() with parameters:
akasicdb.cypher(
graph_name NAME, -- Name of the graph to query
query_string TEXT, -- Graph query to execute
parameters JSONB -- Parameter values in JSON format
);
Graph queries use GQL/openCypher-style syntax with the SQL/GQL limitations described below. The query_string must be enclosed in dollar quotes ($$). After calling akasicdb.cypher(), you must add an AS clause so that the graph query results can be handled as tuples in the SQL query.
Basic Traversal¶
-- Retrieve the full name of the customer whose first name is Margaret
SELECT *
FROM akasicdb.cypher('retail_graph', $$
MATCH (c:v_customer)
WHERE c.first_name = 'Margaret'
RETURN
c.first_name as first_name,
c.last_name as last_name
$$) as (
first_name varchar,
last_name varchar
);
-- Find other customers who purchased items that Margaret Farias also purchased
SELECT *
FROM akasicdb.cypher('retail_graph', $$
MATCH (c1:v_customer)-[:buy]->(i:v_item)<-[:buy]-(c2:v_customer)
WHERE c1.first_name = 'Margaret'
AND c1.last_name = 'Farias'
AND c1.vertex_id <> c2.vertex_id
RETURN
c2.first_name as first_name,
c2.last_name as last_name
$$) as (
first_name varchar,
last_name varchar
);
WITH Clause¶
-- Find items sold by stores where Margaret Farias made purchases
SELECT item_name
FROM akasicdb.cypher('retail_graph', $$
MATCH (c:v_customer)-[:buy]->(i1:v_item)<-[:sell]-(s1:v_store)
WHERE c.first_name = 'Margaret'
AND c.last_name = 'Farias'
WITH DISTINCT s1.vertex_id AS store_id
MATCH (s2:v_store)-[:sell]->(i2:v_item)
WHERE s2.vertex_id = store_id
RETURN
DISTINCT i2.name AS item_name
$$) as (
item_name char
);
Aggregation¶
-- Find the names and quantities of items purchased by Margaret Farias at a specific store
SELECT item_name, cnt
FROM akasicdb.cypher('retail_graph', $$
MATCH (c:v_customer)-[:buy]->(i:v_item)<-[:sell]-(s:v_store)
WHERE s.s_id = 1
AND c.first_name = 'Margaret'
AND c.last_name = 'Farias'
RETURN
i.name AS item_name,
count(i.name) AS cnt
$$) as (
item_name char,
cnt integer
)
VLE (Variable-Length Edge) Pattern¶
-- Find customers within 1 to 3 hops from Latisha Hamilton
-- in a customer network built with 'co_purchase' edges
SELECT *
FROM akasicdb.cypher('retail_graph', $$
MATCH (c1:v_customer)-[:co_purchase*1..3 SHORTEST]->(c2:v_customer)
WHERE c1.first_name = 'Latisha' AND c1.last_name = 'Hamilton'
RETURN
c2.first_name as first_name,
c2.last_name as last_name
$$) as (
first_name varchar,
last_name varchar
);
- VLE (Variable-Length Edge) and TC (Transitive Closure) patterns have the following limitations:
- Only one edge label is allowed, and the edge must connect vertices with the same label.
- Traversal can be very slow if the starting vertex, such as
c1in the example above, is not filtered. - Traversal performance may degrade as the hop count increases. Specifying
SHORTESTcan help maintain good performance even with larger hop counts.
Using Parameters in Graph Queries¶
-- Retrieve the full name of the customer whose name matches the parameter
-- 'customer_name', with the value 'Margaret'.
SELECT *
FROM akasicdb.cypher('retail_graph', $$
MATCH (c:v_customer)
WHERE c.first_name = $customer_name
RETURN
c.first_name as first_name,
c.last_name as last_name
$$, '{"customer_name":"Margaret"}') as (
first_name varchar,
last_name varchar
);
- In a graph query, parameters are represented as symbols that start with $, such as
$customer_namein the example above. - Parameter values are passed to the function in JSON format.
-- Retrieve the full name of the customer whose c_id matches the parameter
-- 'customer_id', with the value '1'.
SELECT *
FROM akasicdb.cypher('retail_graph', $$
MATCH (c:v_customer)
WHERE c.c_id = $customer_id::integer
RETURN
c.first_name as first_name,
c.last_name as last_name
$$, '{"customer_id":1}') as (
first_name varchar,
last_name varchar
);
- Parameter values are treated as
TEXTby default within the query - To use another type, such as an
integer, explicitly cast the parameter in the query. - SQL/GQL uses SQL-style casts, such as
::integer, instead of openCypher-style functions liketoInteger(). If the type name contains special characters, it should be enclosed in single quotes, such as::'int[]'.
Notes on Using SQL/GQL¶
Graph queries in SQL/GQL are similar to openCypher, but there are some differences in the supported syntax and usage. Unsupported syntax may be added in future updates.
Before using the examples below, keep these pattern rules in mind:
- When a vertex or edge first appears in a graph pattern, it must specify exactly one label. Use patterns such as
(c:v_customer)-[r:buy]->(i:v_item)instead of unlabeled or multi-label patterns. -
Every edge is directed. Traversals must choose either the forward direction (
->) or the reverse direction (<-); undirected edge patterns such as--are not supported. -
OPTIONAL MATCHis currently not supported. Similar behavior can be achieved in SQL/GQL by using SQL outer joins. -
Set operations such as
UNIONare currently not supported withinakasicdb.cypher(). To achieve similar behavior, use SQL set operations outside theakasicdb.cypher()call.openCypher SQL/GQL -
Property maps such as
(v:vertex_label {key: "Value"})are not supported. Use property conditions in theWHEREclause to express the same logic.openCypher SQL/GQL -
The
exists()function and path variables are currently not supported. -
WITHandRETURNclauses do not support returning vertices or edges directly. -
INis currently not supported withinakasicdb.cypher(). -
The openCypher
collect()function is not supported. Use PostgreSQL’sarray_agg()function instead.openCypher SQL/GQL -
Array indexing starts from 1.
-
List comprehensions are currently not supported.
-
CALLsubqueries are currently not supported. -
openCypher helper functions such as
labels(n),type(r), andproperties(n)are currently not supported. Specify labels in patterns and access properties directly by name. -
The openCypher
id()function is currently not supported. Use the internal ID properties directly, such asn.vertex_idfor vertices andr.edge_idfor edges. -
ORDER BYcannot reference an alias created in the sameRETURNclause. Order by the original expression or property inside the graph query, or sort by the returned alias in the outer SQL query.