Skip to main content
Version: 0.3.36

Graph Queries

How to follow relations between nodes and walk the hierarchy from SQL and from the JavaScript SDK. Relations are created with RELATE (see the Graph Model); this page is about reading them.

Relations of one node

Anchor a pattern on the node and let the direction of the edge decide what you get back. Filters go in the WHERE clause between MATCH and COLUMNS.

-- outgoing: what does alice point at?
SELECT * FROM GRAPH_TABLE(
MATCH (a)-[r]->(other) WHERE a.path = '/alice'
COLUMNS (other.path AS target, r.relation_type AS type, r.weight AS weight)
);

-- incoming: who points at alice?
SELECT * FROM GRAPH_TABLE(
MATCH (a)<-[r]-(other) WHERE a.path = '/alice'
COLUMNS (other.path AS source, r.relation_type AS type)
);
{"columns":["source","type"],
"rows":[{"source":"/bob","type":"follows"},
{"source":"/carol","type":"follows"},
{"source":"/dave","type":"follows"}]}

Run the two queries separately when you need both directions; an edge pattern without an arrow currently matches in the stored direction only.

Filter by relation type

Name the type in the edge pattern. Types match exactly, including case.

SELECT * FROM GRAPH_TABLE(
MATCH (a)<-[:follows]-(f:Person) WHERE a.path = '/alice'
COLUMNS (f.name AS follower, f.city AS city)
);

f.city reads the city property; f.properties->>'city' is the same thing.

Follow a chain

-- people two hops upstream of alice
SELECT DISTINCT start
FROM GRAPH_TABLE(
MATCH (a)<-[:follows]-(b)<-[:follows]-(c) WHERE a.path = '/alice'
COLUMNS (c.name AS start)
) AS g;

-- everything reachable from dave in one to three hops
SELECT DISTINCT reached
FROM GRAPH_TABLE(
MATCH (a)-[:follows]->{1,3}(b) WHERE a.path = '/dave'
COLUMNS (b.name AS reached)
) AS g;

GRAPH_TABLE returns one row per path, so DISTINCT collapses nodes that are reachable more than one way.

Count and group

Treat the GRAPH_TABLE result as a table:

SELECT followed, COUNT(*) AS followers
FROM GRAPH_TABLE(
MATCH (a:Person)-[:follows]->(b:Person)
COLUMNS (b.name AS followed)
) AS g
GROUP BY followed
ORDER BY followers DESC;

The complete pattern grammar, path variables and shortest-path selectors are in the GRAPH_TABLE reference.

Hierarchy traversal

Paths are the tree. These predicates and functions walk it without a graph pattern:

-- direct children
SELECT path FROM 'social' WHERE CHILD_OF('/archive');

-- all descendants, or descendants down to a depth
SELECT path FROM 'social' WHERE DESCENDANT_OF('/archive');
SELECT path FROM 'social' WHERE DESCENDANT_OF('/archive', 1);

-- parent path and depth of each node under a prefix
SELECT path, PARENT(path) AS parent, DEPTH(path) AS depth
FROM 'social'
WHERE PATH_STARTS_WITH(path, '/archive');
{"columns":["path","parent","depth"],
"rows":[{"path":"/archive","parent":"/","depth":1},
{"path":"/archive/team","parent":"/archive","depth":2},
{"path":"/archive/team/erin","parent":"/archive/team","depth":3}]}

DESCENDANT_OF returns parents before children (pre-order), and children keep their editorial order; see Path functions for the __order and __tree_order columns.

JavaScript SDK

The @raisindb/client package talks to the WebSocket API. Relation methods take paths and default to the workspace of the client:

import { RaisinClient } from '@raisindb/client';

const client = new RaisinClient('ws://localhost:8090/sys/default/docs-graph');
await client.connect();
await client.authenticate({ username: 'admin', password: '…' });

const nodes = client.database('docs-graph').workspace('social').nodes();

// create and remove an edge
await nodes.addRelation('/bob', 'likes', '/graph-intro', 0.7); // true
await nodes.removeRelation('/bob', '/graph-intro'); // true

// both directions of one node
const rels = await nodes.getRelationships('/alice');
// { outgoing: [{ target, workspace, target_node_type, relation_type, weight }],
// incoming: [{ source_workspace, source_node_id, relation: { … } }] }

// direct children in editorial order
const children = await nodes.listChildren('/archive'); // Node[]

addRelation accepts an options object instead of the weight when the target lives in another workspace: { targetWorkspace: 'places', weight: 1 }.

Next steps