Running Cypher fragments
We can use Cypher as a safe, graph-aware, partially compiled scripting language within APOC.
Procedure Overview
The supported procedures are described in the table below:
type | qualified name | signature | description |
---|---|---|---|
procedure |
|
|
apoc.cypher.doIt(fragment, params) yield value - executes writing fragment with the given parameters |
procedure |
|
|
apoc.cypher.run(fragment, params) yield value - executes reading fragment with the given parameters |
procedure |
|
|
apoc.cypher.runMany('cypher;\nstatements;',{params},[{statistics:true,timeout:10}]) - runs each semicolon separated statement and returns summary - currently no schema operations |
procedure |
|
|
|
procedure |
|
|
|
procedure |
|
|
apoc.cypher.mapParallel(fragment, params, list-to-parallelize) yield value - executes fragment in parallel batches with the list segments being assigned to _ |
procedure |
|
|
apoc.cypher.mapParallel2(fragment, params, list-to-parallelize) yield value - executes fragment in parallel batches with the list segments being assigned to _ |
function |
|
|
use either apoc.cypher.runFirstColumnMany for a list return or apoc.cypher.runFirstColumnSingle for returning the first row of the first column |
function |
|
|
apoc.cypher.runFirstColumnMany(statement, params) - executes statement with given parameters, returns first column only collected into a list, params are available as identifiers |
function |
|
|
apoc.cypher.runFirstColumnSingle(statement, params) - executes statement with given parameters, returns first element of the first column only, params are available as identifiers |
Example: Fast Node-Counts by Label
We can quickly compute the number of nodes for a specific label using the count
function, but only if that’s the only single thing in the query.
For example:
MATCH (:Person) RETURN count(*);
We can also combine several with UNION ALL
:
MATCH (:Person) RETURN count(*)
UNION ALL
MATCH (:Movie) RETURN count(*);
But we can’t do the same thing using the WITH
clause:
MATCH (:Person)
WITH count(*) as people
MATCH (:Movie) RETURN people, count(*) as movies;
This query will work out the count by iterating over all nodes, which is a very slow operation
We can use apoc.cypher.run
to construct the COUNT()
statements and run each of them individually, so it completes in a few ms.
CALL db.labels() yield label
CALL apoc.cypher.run("match (:`"+label+"`) return count(*) as count", null) yield value
return label, value.count as count
You can use a similar approach to get the property-keys per label:
CALL db.labels() yield label
CALL apoc.cypher.run("MATCH (n:`"+label+"`) RETURN keys(n) as keys LIMIT 1",null) yield value
RETURN label, value.keys as keys