Skip to main content
Version: 0.1.0

Path Functions

Functions for hierarchical path manipulation and querying.

DEPTH

Calculate the depth of a hierarchical path.

Syntax

DEPTH(path)INT

Parameters

ParameterTypeDescription
pathPATHHierarchical path

Return Value

INT - Number of path segments (depth in hierarchy).

Examples

SELECT DEPTH('/content');
-- Result: 1

SELECT DEPTH('/content/blog/post1');
-- Result: 3

SELECT DEPTH('/');
-- Result: 0

SELECT
__path,
DEPTH(__path) AS depth
FROM nodes
ORDER BY depth;

-- Find all nodes at specific depth
SELECT * FROM nodes
WHERE DEPTH(__path) = 2;

Notes

  • Root path / has depth 0
  • Each segment adds 1 to depth
  • Useful for hierarchy level queries

PARENT

Get the parent path, optionally going up multiple levels.

Syntax

PARENT(path [, levels]) → PATH

Parameters

ParameterTypeDescription
pathPATHChild path
levelsINTOptional. Number of levels up (default: 1)

Return Value

PATH - Parent path, or NULL if at root.

Examples

SELECT PARENT('/content/blog/post1');
-- Result: '/content/blog'

SELECT PARENT('/content/blog/post1', 2);
-- Result: '/content'

SELECT PARENT('/content/blog/post1', 3);
-- Result: '/'

SELECT PARENT('/', 1);
-- Result: NULL

SELECT
__path,
PARENT(__path) AS parent_path,
PARENT(__path, 2) AS grandparent_path
FROM nodes;

-- Group by parent
SELECT
PARENT(__path) AS parent,
COUNT(*) AS child_count
FROM nodes
GROUP BY PARENT(__path);

Notes

  • Returns NULL if going above root
  • Default is 1 level up
  • Negative levels not allowed

ANCESTOR

Get ancestor at a specific absolute depth from root.

Syntax

ANCESTOR(path, depth) → PATH

Parameters

ParameterTypeDescription
pathPATHDescendant path
depthINTAbsolute depth from root (0 = root)

Return Value

PATH - Ancestor path at specified depth, or NULL if path is shallower.

Examples

SELECT ANCESTOR('/content/blog/posts/2024/post1', 0);
-- Result: '/'

SELECT ANCESTOR('/content/blog/posts/2024/post1', 1);
-- Result: '/content'

SELECT ANCESTOR('/content/blog/posts/2024/post1', 2);
-- Result: '/content/blog'

SELECT ANCESTOR('/content/blog', 3);
-- Result: NULL (path not deep enough)

SELECT
__path,
ANCESTOR(__path, 1) AS section,
ANCESTOR(__path, 2) AS subsection
FROM nodes
WHERE DEPTH(__path) >= 2;

-- Group by top-level section
SELECT
ANCESTOR(__path, 1) AS section,
COUNT(*) AS total_nodes
FROM nodes
WHERE DEPTH(__path) > 0
GROUP BY section;

Notes

  • Depth 0 always returns root /
  • Returns NULL if path is shallower than requested depth
  • Useful for grouping by hierarchy level

PATH_STARTS_WITH

Check if a path starts with a given prefix.

Syntax

PATH_STARTS_WITH(path, prefix)BOOLEAN

Parameters

ParameterTypeDescription
pathPATHPath to check
prefixPATHPrefix to match

Return Value

BOOLEAN - true if path starts with prefix, false otherwise.

Examples

SELECT PATH_STARTS_WITH('/content/blog/post1', '/content');
-- Result: true

SELECT PATH_STARTS_WITH('/content/blog/post1', '/content/blog');
-- Result: true

SELECT PATH_STARTS_WITH('/content/blog/post1', '/docs');
-- Result: false

SELECT PATH_STARTS_WITH('/content', '/content');
-- Result: true (exact match)

SELECT * FROM nodes
WHERE PATH_STARTS_WITH(__path, '/content/blog');

-- Find all content under multiple sections
SELECT * FROM nodes
WHERE PATH_STARTS_WITH(__path, '/content/docs')
OR PATH_STARTS_WITH(__path, '/content/guides');

Notes

  • Exact match returns true
  • Prefix must be complete path segments
  • Case-sensitive comparison

CHILD_OF

Check if a path is a direct child of a parent path.

Syntax

CHILD_OF(path, parent)BOOLEAN

Parameters

ParameterTypeDescription
pathPATHChild path to check
parentPATHParent path

Return Value

BOOLEAN - true if path is a direct child of parent, false otherwise.

Examples

SELECT CHILD_OF('/content/blog', '/content');
-- Result: true

SELECT CHILD_OF('/content/blog/post1', '/content');
-- Result: false (grandchild, not direct child)

SELECT CHILD_OF('/content/blog/post1', '/content/blog');
-- Result: true

-- Find direct children of a path
SELECT * FROM nodes
WHERE CHILD_OF(__path, '/content/docs');

-- Count direct children
SELECT
PARENT(__path) AS parent,
COUNT(*) AS direct_children
FROM nodes
WHERE CHILD_OF(__path, '/content')
GROUP BY PARENT(__path);

Notes

  • Only direct children return true
  • Grandchildren and deeper descendants return false
  • Use DESCENDANT_OF for any depth

DESCENDANT_OF

Check if a path is a descendant of an ancestor path.

Syntax

DESCENDANT_OF(path, ancestor [, max_depth])BOOLEAN

Parameters

ParameterTypeDescription
pathPATHDescendant path to check
ancestorPATHAncestor path
max_depthINTOptional. Maximum depth difference

Return Value

BOOLEAN - true if path is a descendant of ancestor, false otherwise.

Examples

SELECT DESCENDANT_OF('/content/blog/posts/post1', '/content');
-- Result: true

SELECT DESCENDANT_OF('/content/blog', '/content');
-- Result: true

SELECT DESCENDANT_OF('/content', '/content');
-- Result: false (not a descendant of itself)

SELECT DESCENDANT_OF('/docs', '/content');
-- Result: false

-- With max depth
SELECT DESCENDANT_OF('/content/blog/posts/post1', '/content', 2);
-- Result: true (depth difference is 3, within max of 2? false if strict)

-- Find all descendants
SELECT * FROM nodes
WHERE DESCENDANT_OF(__path, '/content/blog');

-- Find descendants within 2 levels
SELECT * FROM nodes
WHERE DESCENDANT_OF(__path, '/content', 2);

-- Exclude direct children
SELECT * FROM nodes
WHERE DESCENDANT_OF(__path, '/content')
AND NOT CHILD_OF(__path, '/content');

Notes

  • Does not include the path itself
  • Use PATH_STARTS_WITH to include the path itself
  • Optional max_depth limits descendant depth
  • Useful for subtree queries

REFERENCES

Check if a node has a reference to a target path.

Syntax

REFERENCES(target_path)BOOLEAN

Parameters

ParameterTypeDescription
target_pathPATHPath being referenced

Return Value

BOOLEAN - true if current node references target, false otherwise.

Examples

-- Find all nodes referencing a specific path
SELECT * FROM nodes
WHERE REFERENCES('/content/products/widget1');

-- Find nodes with any references
SELECT
__path,
COUNT(*) AS reference_count
FROM nodes
WHERE REFERENCES(__path)
GROUP BY __path;

-- Find pages referencing a category
SELECT p.__path, p.title
FROM pages p
WHERE REFERENCES('/categories/tutorials');

Notes

  • Uses reverse reference index for performance
  • Checks outgoing references from current node
  • Useful for finding relationships

NEIGHBORS

Get neighboring nodes connected by graph relationships.

Syntax

NEIGHBORS(node_id, direction, relation_type)TABLE

Parameters

ParameterTypeDescription
node_idUUIDID of the source node
directionTEXTDirection: 'outgoing', 'incoming', or 'both'
relation_typeTEXTOptional. Filter by relationship type

Return Value

TABLE - Set of neighboring node IDs and relationship metadata.

Examples

-- Find all outgoing neighbors
SELECT * FROM NEIGHBORS(__id, 'outgoing')
FROM pages
WHERE __path = '/content/home';

-- Find incoming relationships of a specific type
SELECT * FROM NEIGHBORS(__id, 'incoming', 'links_to')
FROM pages
WHERE title = 'About';

-- Find all connected nodes (both directions)
SELECT * FROM NEIGHBORS(__id, 'both')
FROM pages
WHERE __path = '/content/hub';

Notes

  • Returns an empty set if the node has no relationships in the given direction
  • When relation_type is omitted, returns neighbors for all relationship types
  • Uses the graph index for efficient lookups

Examples

Hierarchy Depth Query

-- Show hierarchy structure with indentation
SELECT
DEPTH(__path) AS depth,
REPEAT(' ', DEPTH(__path)) || title AS indented_title,
__path
FROM nodes
WHERE PATH_STARTS_WITH(__path, '/content')
ORDER BY __path;

Find Siblings

-- Find all siblings of a specific node
SELECT * FROM nodes
WHERE PARENT(__path) = PARENT('/content/blog/post1')
AND __path != '/content/blog/post1';
-- Generate breadcrumb trail
SELECT
ANCESTOR(__path, 1) AS level1,
ANCESTOR(__path, 2) AS level2,
ANCESTOR(__path, 3) AS level3,
__path AS current
FROM nodes
WHERE __path = '/content/docs/guides/sql/intro';

Section Statistics

-- Count nodes by top-level section
SELECT
ANCESTOR(__path, 1) AS section,
COUNT(*) AS node_count,
AVG(DEPTH(__path)) AS avg_depth
FROM nodes
WHERE DEPTH(__path) > 0
GROUP BY section
ORDER BY node_count DESC;

Subtree Query

-- Get all nodes in a subtree with depth limit
SELECT
__path,
title,
DEPTH(__path) - DEPTH('/content/docs') AS relative_depth
FROM nodes
WHERE DESCENDANT_OF(__path, '/content/docs', 3)
OR __path = '/content/docs'
ORDER BY __path;

Parent-Child Join

-- Join parents with their children
SELECT
p.__path AS parent_path,
p.title AS parent_title,
c.__path AS child_path,
c.title AS child_title
FROM nodes p
JOIN nodes c ON CHILD_OF(c.__path, p.__path)
WHERE p.__path = '/content/blog';

Find Orphans

-- Find nodes without valid parents
SELECT * FROM nodes n1
WHERE NOT EXISTS (
SELECT 1 FROM nodes n2
WHERE n2.__path = PARENT(n1.__path)
)
AND __path != '/';

Hierarchy Level Grouping

-- Group by hierarchy level
SELECT
CASE DEPTH(__path)
WHEN 1 THEN 'Top Level'
WHEN 2 THEN 'Second Level'
WHEN 3 THEN 'Third Level'
ELSE 'Deep'
END AS level,
COUNT(*) AS count
FROM nodes
GROUP BY level
ORDER BY MIN(DEPTH(__path));