Library API
gcyphrq can be used as a library in Node.js and TypeScript projects. This page covers all public APIs, types, and usage patterns.
Installation
npm install gcyphrq
Quick Start
import { executeQuery } from 'gcyphrq';
const graphData = {
nodes: [
{ key: 'alice', attributes: { label: 'User', name: 'Alice', age: 30 } },
{ key: 'bob', attributes: { label: 'User', name: 'Bob', age: 25 } },
],
edges: [
{ source: 'alice', target: 'bob', attributes: { type: 'FRIEND' } },
],
};
const results = await executeQuery(graphData, 'MATCH (u:User) RETURN u.name, u.age');
console.log(results);
// [ { name: 'Alice', age: 30 }, { name: 'Bob', age: 25 } ]
With an existing Graphology graph
If you already have a Graphology Graph instance (built externally or programmatically), you can pass it directly:
import { executeQuery } from 'gcyphrq';
import Graph from 'graphology';
const graph = new Graph();
graph.addNode('alice', { label: 'User', name: 'Alice', age: 30 });
graph.addNode('bob', { label: 'User', name: 'Bob', age: 25 });
graph.addEdge('alice', 'bob', { type: 'FRIEND' });
const results = await executeQuery(graph, 'MATCH (u:User) RETURN u.name, u.age');
console.log(results);
// [ { name: 'Alice', age: 30 }, { name: 'Bob', age: 25 } ]
No graph data reconstruction needed — the library builds indexes directly from the graph instance.
API Reference
executeQuery(graphData, query, opts?)
Execute a Cypher query against a graph and return results as plain JSON. This is the simplest entry point — pass in graph data and a query string, get back an array of result rows.
Parameters:
| Parameter | Type | Description |
|---|---|---|
graphData |
GraphInput |
Graph data in Graphology JSON format |
query |
string |
A Cypher query string |
opts |
IndexBuildOptions (optional) |
Configuration for label/edge-type property names and warnings |
Returns: Promise<ResultRow[]> — promise resolving to an array of result rows
Throws: GraphError if graph data is invalid, Error if the query is invalid
import { executeQuery } from 'gcyphrq';
const results = await executeQuery(graphData, 'MATCH (u:User) RETURN u.name');
Custom Label/Edge-Type Property Names
By default gcyphrq reads label from node attributes and type from edge attributes. Use the config option to point at different property names:
import { executeQuery } from 'gcyphrq';
const results = await executeQuery(graphData, 'MATCH (s:Service) RETURN s.name', {
config: { labelProperty: 'kind', edgeTypeProperty: 'rel' },
});
Variable-Length Traversal Limits
Unbounded variable-length patterns like [*1..] are subject to safety limits to prevent OOM on large or dense graphs:
maxVariableLengthDepth(default:10) — Maximum depth for patterns without an explicit upper bound. Explicit bounds like[*1..50]always take precedence.maxVariableLengthPaths(default:100_000) — Maximum number of paths emitted per (startNode, hop). When exceeded, a warning is emitted and traversal stops.
import { executeQuery } from 'gcyphrq';
// Increase depth limit for sparse graphs where you need deeper traversal
const results = await executeQuery(graphData,
'MATCH (a:Service)-[*1..]->(b:Database) RETURN a, b',
{
config: { maxVariableLengthDepth: 50 },
},
);
// Tighten path limit for interactive use
const results2 = await executeQuery(graphData,
'MATCH (a)-[*1..]->(b) RETURN a, b',
{
config: { maxVariableLengthPaths: 10_000 },
},
);
Tip: Always prefer explicit bounds (e.g.,
[*1..10]) over relying on the default. The engine emits a warning for unbounded patterns to remind you.
executeQuery(graph, query, opts?) — with a Graphology Graph
Execute a Cypher query against an existing Graphology Graph instance. Indexes are built automatically from the graph.
Parameters:
| Parameter | Type | Description |
|---|---|---|
graph |
Any Graphology Graph |
An existing graph instance (from graphology or the library’s Graph wrapper) |
query |
string |
A Cypher query string |
opts |
IndexBuildOptions (optional) |
Configuration for label/edge-type property names and warnings |
Returns: Promise<ResultRow[]> — promise resolving to an array of result rows
Throws: Error if the query is invalid
import { executeQuery } from 'gcyphrq';
import Graph from 'graphology';
const graph = new Graph();
graph.addNode('alice', { label: 'User', name: 'Alice' });
graph.addNode('bob', { label: 'User', name: 'Bob' });
graph.addEdge('alice', 'bob', { type: 'FRIEND' });
const results = await executeQuery(graph, 'MATCH (u:User) RETURN u.name');
createGraph(graphData, opts?: GraphOptions)
Build a GraphInstance from a graph data object. Validates the data and constructs a Graphology-backed graph that the Cypher engine can query.
Parameters:
| Parameter | Type | Description |
|---|---|---|
graphData |
GraphInput |
Graph data in Graphology JSON format |
opts |
GraphOptions (optional) |
Only supports onWarning callback. Does not accept config (label/edge-type property names) — use it with buildGraphIndexes or executeQuery instead |
Returns: GraphInstance
Throws: GraphError if graph data is invalid
import { createGraph } from 'gcyphrq';
const graph = createGraph(graphData);
parseCypher(query)
Parse a Cypher query string into an AST. The returned AST can be passed to GraphEngine.execute() or inspected programmatically.
Parameters:
| Parameter | Type | Description |
|---|---|---|
query |
string |
A Cypher query string |
Returns: CypherAST — either AdvancedCypherAST (single query) or UnionQueryAST (UNION query)
Throws: Error if the query cannot be parsed
import { parseCypher } from 'gcyphrq';
const ast = parseCypher('MATCH (u:User) RETURN u');
// ast.type is 'Query' for single queries, 'UnionQuery' for UNION queries
if (ast.type === 'Query') {
console.log(ast.stages[0].clause.sourcePattern.labels); // ['User']
}
explainQuery(query)
Generate an explain plan for a Cypher query without executing it. Walks the parsed AST and produces a structured plan showing query stages, variable bindings, and descriptions.
Parameters:
| Parameter | Type | Description |
|---|---|---|
query |
string |
A Cypher query string |
Returns: ExplainPlan — structured plan with stages and variable bindings
import { explainQuery } from 'gcyphrq';
const plan = explainQuery('MATCH (u:User)-[r:FRIEND]->(f:User) RETURN u, f');
console.log(JSON.stringify(plan, null, 2));
// {
// query: 'MATCH (u:User)-[r:FRIEND]->(f:User) RETURN u, f',
// stages: [
// { index: 0, type: 'MATCH', description: '...', variables: ['u', 'f', 'r'], details: {...} },
// { index: 1, type: 'RETURN', description: '...', variables: ['u', 'f'], details: {...} }
// ],
// finalVariables: ['u', 'f']
// }
The plan includes:
query— the original query stringstages— array of query stages (MATCH, WITH, RETURN, etc.) with type, description, variables, and detailsfinalVariables— variables bound at the end of the queryunion—trueif this is a UNION query
buildGraphIndexes
Build pre-computed indexes for fast query execution. Pass the returned indexes to GraphEngine for O(1) label, property, and edge-type lookups instead of full-graph scans.
Three overloads:
| Signature | Description |
|---|---|
buildGraphIndexes(graph, opts?) |
Build indexes from an existing Graphology graph |
buildGraphIndexes(data, opts?) |
Build indexes from graph data alone (builds graph internally) |
buildGraphIndexes(data, graph, opts?) |
Build indexes from graph data + graph instance |
All overloads accept an optional opts argument of type IndexBuildOptions.
Returns: GraphIndexes
import { buildGraphIndexes, GraphEngine } from 'gcyphrq';
import Graph from 'graphology';
const graph = new Graph();
graph.addNode('alice', { label: 'User', name: 'Alice' });
const indexes = buildGraphIndexes(graph);
const engine = new GraphEngine(graph, indexes);
Custom Label/Edge-Type Property Names
By default gcyphrq reads label from node attributes and type from edge attributes. Use opts.config to point at different property names:
import { buildGraphIndexes, GraphEngine } from 'gcyphrq';
const graph = createGraph(graphData);
const indexes = buildGraphIndexes(graph, {
config: { labelProperty: 'kind', edgeTypeProperty: 'rel' },
});
const engine = new GraphEngine(graph, indexes);
GraphEngine
The Cypher query engine class. Accepts a GraphInstance and executes parsed ASTs.
Constructor: new GraphEngine(graph: GraphInstance, indexes?: GraphIndexes, onWarning?: (msg: string) => void, extensionFunctions?: Map, extensionAggregations?: Map)
| Parameter | Type | Description |
|---|---|---|
graph |
GraphInstance |
A Graphology graph instance |
indexes |
GraphIndexes (optional) |
Pre-computed indexes for O(1) lookups. Without indexes, the engine falls back to full-graph scans |
onWarning |
(msg: string) => void (optional) |
Callback for non-fatal warnings during query execution |
extensionFunctions |
Map<string, { fn, extName }> (optional) |
Extension scalar functions. See Extension API |
extensionAggregations |
Map<string, { fn, extName }> (optional) |
Extension aggregation functions. See Extension API |
Extensions: For extension functions, use
registerFunctionExtension()+executeQuery()instead of constructingGraphEnginedirectly. Extension functions are automatically wired throughexecuteQuery.
Methods:
| Method | Parameters | Returns | Description |
|---|---|---|---|
execute(ast) |
ast: AdvancedCypherAST |
Promise<ResultRow[]> |
Execute a single parsed AST against the graph |
executeUnion(ast) |
ast: UnionQueryAST |
Promise<ResultRow[]> |
Execute a UNION/UNION ALL AST. Aligns columns by name and deduplicates for UNION |
import { GraphEngine, buildGraphIndexes, parseCypher } from 'gcyphrq';
import Graph from 'graphology';
const graph = new Graph();
graph.addNode('alice', { label: 'User', name: 'Alice' });
const indexes = buildGraphIndexes(graph);
const engine = new GraphEngine(graph, indexes);
const ast = parseCypher('MATCH (u:User) RETURN u.name');
const results = await engine.execute(ast);
Tip: For best performance, always pass pre-computed indexes to
GraphEngine. Without indexes, every label and property lookup triggers a full-graph scan.Note: Indexes are invalidated after
CREATE/SET/DELETE/REMOVEmutations. Subsequent MATCH/WITH stages within the same query fall back to full-graph scans to see updated graph state.
Graph
The Graphology wrapper class. Use this when you need to build a graph programmatically (node-by-node) instead of from a data object.
Constructor:
new Graph(options?: { type?: 'directed' | 'undirected' | 'mixed' })
Defaults to 'directed'. For mixed graphs, pass { undirected: true } in edge attributes to create bidirectional edges.
Methods:
| Method | Parameters | Returns | Description |
|---|---|---|---|
addNode(id, attrs?) |
id: string, attrs?: Record<string, unknown> |
void |
Add a node with optional attributes |
addEdge(a, b, attrs?) |
a: string, b: string, attrs?: Record<string, unknown> |
void |
Add an edge (directed by default; use { undirected: true } in mixed graphs) |
getNodeAttributes(id) |
id: string |
Record<string, unknown> |
Get node attributes |
getEdgeAttributes(id) |
id: string |
Record<string, unknown> |
Get edge attributes |
filterNodes(fn) |
fn: (id, attrs) => boolean |
string[] |
Filter nodes by predicate |
forEachOutboundEdge(id, cb) |
id: string, cb: callback |
void |
Iterate outbound edges |
forEachInboundEdge(id, cb) |
id: string, cb: callback |
void |
Iterate inbound edges |
forEachEdge(id, cb) |
id: string, cb: callback |
void |
Iterate all edges (undirected) |
setNodeAttribute(id, attr, value) |
id: string, attr: string, value: unknown |
void |
Set a node attribute |
hasNode(id) |
id: string |
boolean |
Check if node exists |
dropNode(id) |
id: string |
void |
Remove a node and its edges |
type (getter) |
— | 'directed' \| 'undirected' \| 'mixed' |
Graph type |
order |
— | number |
Number of nodes in the graph |
import { Graph, GraphEngine } from 'gcyphrq';
const graph = new Graph();
graph.addNode('alice', { label: 'User', name: 'Alice' });
graph.addNode('bob', { label: 'User', name: 'Bob' });
graph.addEdge('alice', 'bob', { type: 'FRIEND' });
const engine = new GraphEngine(graph);
GraphError
Error class thrown when graph data validation fails.
import { GraphError, createGraph } from 'gcyphrq';
try {
createGraph({ nodes: [], edges: [] });
} catch (err) {
if (err instanceof GraphError) {
console.error('Graph validation failed:', err.message);
}
}
Extension API
gcyphrq supports pluggable extensions for non-JSON input formats and custom functions.
See the Available Extensions table for a list of published extensions.
convertWithExtension(extensionName, context)
Load a graph-input extension and convert file content to GraphInput.
Parameters:
| Parameter | Type | Description |
|---|---|---|
extensionName |
string |
Extension name (key in gcyphrqExtensions) |
context |
GraphInputExtensionContext |
File content and optional config |
Returns: Promise<{ graph: GraphInput; cacheable: boolean }>
The cacheable field indicates whether the extension’s output is eligible for CLI-side caching (true unless the extension manifest sets cacheable: false).
import { convertWithExtension, executeQuery } from 'gcyphrq';
import { readFileSync } from 'fs';
const content = readFileSync('data.gexf', 'utf-8');
const { graph } = await convertWithExtension('gexf', {
content,
filePath: 'data.gexf',
});
const results = await executeQuery(graph, 'MATCH (n) RETURN n');
Caching note: The CLI automatically caches results from graph-input extensions (see CLI Reference — Graph Caching). This caching is a CLI-layer feature and does not apply when using
convertWithExtensiondirectly as a library. If you need caching in your application, you can implement it aroundconvertWithExtensioncalls or use the CLI for batch processing.
registerFunctionExtension(extensionName)
Load a function extension and register its functions. Multiple extensions can share the same namespace.
Parameters:
| Parameter | Type | Description |
|---|---|---|
extensionName |
string |
Extension name (key in gcyphrqExtensions) |
Returns: Promise<void>
Note on aggregations: Extension “aggregations” registered via
addAggregationare callable as regular functions receiving all arguments directly. For aggregation over multiple rows, combine withcollect():MATCH (n) RETURN myext.myAgg(collect(n.score))
import { registerFunctionExtension, executeQuery } from 'gcyphrq';
await registerFunctionExtension('apoc-commons');
await registerFunctionExtension('apoc-crypto');
const results = await executeQuery(graphData, 'RETURN apoc.text.join(", ", ["a","b"])');
listExtensions()
List all available extensions from installed gcyphrq-ext-* packages.
Returns: Array of extension metadata
import { listExtensions } from 'gcyphrq';
const extensions = listExtensions();
for (const ext of extensions) {
console.log(`${ext.name} (${ext.type}) — ${ext.description}`);
}
helpers, validate, and FunctionError
Helper utilities for extension authors to validate function arguments and throw user-friendly errors:
import { helpers, validate, FunctionError } from 'gcyphrq';
// Type predicates
helpers.isString(value);
helpers.isNumber(value);
helpers.isArray(value);
// Argument validator
const { sep, values } = validate(args, (v) => {
v.minCount(2);
v.arg(0, 'sep', helpers.isString);
v.argsFrom(1, 'values');
});
// User-facing validation error
throw new FunctionError('Cannot convert null to integer');
// Engine reports: "Error in apoc.toInt: Cannot convert null to integer"
See Extensions Guide for creating your own extensions.
Usage Patterns
Pattern 1: One-shot query (simplest)
Use executeQuery when you have graph data and just need results:
import { executeQuery } from 'gcyphrq';
const results = await executeQuery(graphData, 'MATCH (u:User) RETURN u.name');
Pattern 2: Reusable graph with multiple queries
Use createGraph + GraphEngine when running multiple queries against the same graph:
import { createGraph, GraphEngine, parseCypher } from 'gcyphrq';
const graph = createGraph(graphData);
const engine = new GraphEngine(graph);
const users = await engine.execute(parseCypher('MATCH (u:User) RETURN u.name'));
const counts = await engine.execute(parseCypher('MATCH (u:User) RETURN count(u)'));
Pattern 3: Programmatic graph construction
Use Graph directly when building the graph from non-JSON sources (database, API, etc.):
import { Graph, GraphEngine, parseCypher } from 'gcyphrq';
const graph = new Graph();
// Build from a database query, API response, etc.
for (const user of users) {
graph.addNode(user.id, { label: 'User', ...user.properties });
}
for (const rel of relationships) {
graph.addEdge(rel.from, rel.to, { type: rel.type });
}
const engine = new GraphEngine(graph);
const results = await engine.execute(parseCypher('MATCH (u:User) RETURN u'));
Pattern 4: External Graphology graph
Use the library with any existing Graphology Graph instance — for example, one built from a database, a file, or another library. The library builds indexes directly from the graph without needing the original data.
import { executeQuery, buildGraphIndexes, GraphEngine, parseCypher } from 'gcyphrq';
import Graph from 'graphology';
// Build graph from any source (database, API, file, etc.)
const graph = new Graph();
for (const node of nodesFromDatabase) {
graph.addNode(node.id, { label: node.label, ...node.properties });
}
for (const edge of edgesFromDatabase) {
graph.addEdge(edge.source, edge.target, { type: edge.type });
}
// One-shot query (indexes built automatically)
const results = await executeQuery(graph, 'MATCH (u:User) RETURN u.name');
// Or with reusable engine and indexes for multiple queries
const indexes = buildGraphIndexes(graph);
const engine = new GraphEngine(graph, indexes);
const users = await engine.execute(parseCypher('MATCH (u:User) RETURN u.name'));
const count = await engine.execute(parseCypher('MATCH (u:User) RETURN count(u)'));
Pattern 5: AST inspection
Use parseCypher to inspect or transform the query AST before execution:
import { parseCypher } from 'gcyphrq';
const ast = parseCypher('MATCH (u:User {name: "Alice"}) RETURN u');
if (ast.type === 'Query') {
console.log(ast.stages[0].clause.sourcePattern.properties);
// { name: 'Alice' }
}
Pattern 6: UNION / UNION ALL
Combine results from multiple query branches:
import { executeQuery } from 'gcyphrq';
const results = await executeQuery(graphData,
'MATCH (u:User {name: "Alice"}) RETURN u.name UNION ALL MATCH (u:User {name: "Bob"}) RETURN u.name',
);
// [ { name: 'Alice' }, { name: 'Bob' } ]
Use UNION (without ALL) to deduplicate the combined result set.
Pattern 7: Mutation followed by query
The engine supports CREATE, SET, DELETE, DETACH DELETE, and REMOVE mutations within queries. Mutations modify the underlying graph in-place:
import { createGraph, GraphEngine, parseCypher } from 'gcyphrq';
const graph = createGraph(graphData);
const engine = new GraphEngine(graph);
// Create a new node
await engine.execute(parseCypher('CREATE (n:User {name: "Charlie"}) RETURN n'));
// Update a node
await engine.execute(parseCypher('MATCH (u:User {name: "Alice"}) SET u.age = 31 RETURN u'));
// Query after mutation
const results = await engine.execute(parseCypher('MATCH (u:User) RETURN u.name, u.age'));
Types
All types are exported and can be imported for use in your own code:
import type {
// Graph data (Graphology JSON format)
GraphInput,
GraphologyFile,
GraphologyNode,
GraphologyEdge,
GraphologyGraphOptions,
// Graph instance
GraphInstance,
GraphIndexes,
// Options
GraphOptions,
IndexBuildOptions,
GraphConfig,
// AST types
AdvancedCypherAST,
UnionQueryAST,
UnionType,
CypherAST,
Stage,
MatchClause,
WithClause,
ReturnClause,
WriteClause,
SetClause,
SetItem,
CallClause,
LoadCsvClause,
NodePattern,
RelationPattern,
Direction,
// Expression types
Expression,
PropertyAccessExpression,
LiteralExpression,
AggregationExpression,
BinaryExpression,
Projection,
OrderByItem,
UnwindClause,
// Result types
ResultRow,
QueryContext,
CypherNode,
CypherEdge,
CypherValue,
CypherLiteral,
SubgraphResult,
// Extension types
GraphInputExtension,
GraphInputExtensionContext,
FunctionExtension,
FunctionRegistry,
ScalarFunction,
AggregationFunction,
ExtensionManifest,
ResolvedExtension,
LoadedExtension,
ArgHelpers,
ArgValidator,
} from 'gcyphrq';
Key Types
GraphInput
Graph data in Graphology JSON format:
type GraphInput = GraphologyFile;
IndexBuildOptions
Options for buildGraphIndexes and executeQuery. Extends GraphOptions with an optional config field.
interface IndexBuildOptions extends GraphOptions {
/** Partial config for label/edge-type property names. */
config?: Partial<GraphConfig>;
}
GraphConfig
The resolved config used internally. The first two fields are required; the traversal limits are optional.
interface GraphConfig {
/** Node attribute key used as the Cypher label (default: `"label"`). */
labelProperty: string;
/** Edge attribute key used as the Cypher relationship type (default: `"type"`). */
edgeTypeProperty: string;
/** Max depth for unbounded variable-length patterns like [*1..] (default: 10). */
maxVariableLengthDepth?: number;
/** Max paths per (startNode, hop) in variable-length traversal (default: 100_000). */
maxVariableLengthPaths?: number;
}
GraphOptions
Options for createGraph. Does not include config (label/edge-type property names).
interface GraphOptions {
/** Callback for non-fatal warnings during graph construction. */
onWarning?: (message: string) => void;
}
GraphologyFile
The Graphology JSON format (primary format):
interface GraphologyFile {
options?: GraphologyGraphOptions;
attributes?: Record<string, unknown>;
nodes: GraphologyNode[];
edges: GraphologyEdge[];
}
interface GraphologyNode {
key: string;
attributes: Record<string, unknown>;
}
interface GraphologyEdge {
key?: string;
source: string;
target: string;
undirected?: boolean; // only effective in mixed graphs; makes the edge bidirectional
attributes: Record<string, unknown>;
}
interface GraphologyGraphOptions {
type?: 'directed' | 'undirected' | 'mixed'; // all three are supported
allowSelfLoops?: boolean; // enables self-loop edges
multi?: boolean; // enables parallel edges between same nodes
}
ResultRow
type ResultRow = Record<string, CypherNode | CypherEdge[] | CypherLiteral | null | undefined>;
Each result row is a plain object mapping projection aliases to their values.
SubgraphResult
Returned by subgraph(), egoGraph(), and connectedComponent() functions:
interface SubgraphResult {
nodes: CypherNode[];
edges: CypherEdge[];
}
Each node and edge includes full attributes from the original graph.
AdvancedCypherAST
interface AdvancedCypherAST {
type: 'Query';
stages: Stage[];
return: ReturnClause | undefined;
}
type Stage =
| { type: 'MATCH'; clause: MatchClause }
| { type: 'WITH'; clause: WithClause }
| { type: 'WRITE'; clause: WriteClause }
| { type: 'MERGE'; clause: MergeClause }
| { type: 'UNWIND'; clause: UnwindClause }
| { type: 'FOREACH'; clause: ForeachClause }
| { type: 'CALL'; clause: CallClause }
| { type: 'LOAD_CSV'; clause: LoadCsvClause };
interface UnionQueryAST {
type: 'UnionQuery';
branches: AdvancedCypherAST[];
unionTypes: (UnionType | null)[]; // null for first branch, then 'UNION' or 'UNION ALL'
orderBy: OrderByItem[] | undefined; // ORDER BY on combined result
skip: number | undefined; // SKIP on combined result
limit: number | undefined; // LIMIT on combined result
}
type UnionType = 'UNION' | 'UNION ALL';
type CypherAST = AdvancedCypherAST | UnionQueryAST;
Error Handling
The library throws two kinds of errors:
GraphError— thrown when graph data validation fails (invalid format, missing fields, duplicate IDs, etc.)Error— thrown when a Cypher query cannot be parsed or executed (syntax errors, unsupported features, etc.)
import { executeQuery, GraphError } from 'gcyphrq';
try {
const results = await executeQuery(graphData, query);
} catch (err) {
if (err instanceof GraphError) {
// Graph data is invalid
console.error('Invalid graph:', err.message);
} else {
// Query error
console.error('Query failed:', err.message);
}
}
TypeScript Configuration
No special TypeScript configuration is needed. The package ships with declaration files (.d.ts) and uses standard ESM module resolution.
For projects using "moduleResolution": "node" (older tsconfig), add:
{
"compilerOptions": {
"moduleResolution": "bundler"
}
}
CommonJS Compatibility
The library is published as ESM only. In CommonJS projects, use dynamic import():
async function main() {
const { executeQuery } = await import('gcyphrq');
const results = await executeQuery(graphData, 'MATCH (u:User) RETURN u.name');
console.log(results);
}
main();
Performance Considerations
executeQuery(graphData, query)builds a new graph for each call. For multiple queries, usecreateGraph+GraphEngineinstead.executeQuery(graph, query)with an existing graph instance reuses the graph but still builds indexes on each call. For multiple queries, usebuildGraphIndexes+GraphEngineinstead.- The engine processes queries in-memory with no caching. Large graphs (>10,000 nodes) may have noticeable query times.
- Variable-length paths use DFS traversal. Unbounded patterns (
[*1..]) default to a max depth of 10 and a path limit of 100,000 per start node. Use explicit bounds (e.g.,[*1..10]) or adjust viaconfig.maxVariableLengthDepth/config.maxVariableLengthPaths.
Next Steps
- Query Guide — Full Cypher syntax reference and query patterns
- Examples — Ready-to-run queries against the bundled example graphs