Developer Guides Getting Started Getting Started What is a Graph Database? Intro to Graph DBs Video Series Concepts: RDBMS to Graph Concepts: NoSQL to Graph Getting Started Resources Neo4j Graph Platform Graph Platform Overview Neo4j Desktop Intro Neo4j Browser Intro… Read more →

Developer Guides

Want to Speak? Get $ back.

Procedures & Functions Gallery

Our community created already a lot of useful user defined procedures and functions. This overview highlights which areas each library covers with some examples. This saves you from implementing existing ones yourself.
You should know what user defined procedures and functions are and how to use them within Cypher.

Awesome Procedures on Cypher (APOC)

With the advent of user defined procedures, many capabilities could be added to Cypher with ease. That’s how the APOC library got started, which developed into a “standard-library” for Neo4j built by the Neo4j community.

Due to the use of internal APIs there are dedicated APOC versions for the different Neo4j versions.

By now it contains 200+ procedures and 70+ functions.

APOC covers much ground, here are some examples for the available functionality.


package # of procedures popular procedure docs link

data api access



database integration



graph algorithms



(virtual) data creation


CALL apoc.create.relationship(startNode,'TYPE',{key:value,…​}, endNode)

transaction control


apoc.periodic.iterate('source-query','work-statement',{batchSize:100, parallel:true})

cypher operations


apoc.cypher.runFile(file or url)

graph data export



graph generation

5, degree, beta, 'label', 'TYPE') // Watts-Strogatz

meta information



time to live, node-expiry



monitoring & operations



manual and schema indexes



cypher triggers on transaction end


apoc.trigger.add(name, statement, selector)

search and expand


apoc.path.expand(startNode, relationshipFilter, labelFilter, minDepth, maxDepth )

apoc.load.json so result


As mentioned before, functions can compute values in any kind of expression or predicate.

package # of functions popular function

date & time conversion


number conversion



general type conversion



type information and checking



collection and map functions


JSON conversion



string functions



hash functions



Learn more about APOC by reading the blog post series on APOC or watch the presentations about it.

APOC itself comes also with a comprehensive and growing documentation site.

Recently added Neo4j Browser guides make parts of that documentation available within your working environment.

Just run: :play within your Neo4j browser to learn interactively.

Neo4j Spatial Procedures

The neo4j-spatial library has been with Neo4j for a long time.

In the past you used it with its Java or REST APIs. Now for Neo4j 3.0 the maintainer, Craig Taverner added procedures for the APIs to integrate the spatial capabilities closely with Cypher.

Spatial Procedure Overview

Neo4j Spatial is packaged as a ZIP file that can be unzipped into the $NEO4J_HOME/plugins directory. After restarting the server, you should be able to use the following procedure calls from Cypher.

Below are some of the most commonly used procedures grouped by type. You can find usage examples below in the legis-graph section.

type procedures (spatial.*)




layer(layer),layers(), layerTypes()

add layers

addLayer(layer, type, config), addLayerWithEncoder(), addPointLayer(layer), addWKTLayer(name, property)

remove layers


add nodes

addNode(layer,node), addNodes(layer,nodes), updateFromWKT(layer,geometry,geoNodeId)

add geometries

addWKT(layer, geometry), addWKTs(layer,geometries)

find / search

bbox(layer, min, max), closest(layer, coordinate, distance), intersects(layer, geometry), withinDistance(layer, coordinate, distance)


asGeometry, asExternalGeometry, decodeGeometry, getFeatureAttributes


importShapefile(uri), importShapefileToLayer(layer, uri)

Using Neo4j Spatial Procedures in legis-graph-spatial

William Lyon demonstrates how to use them in the Legis-Graph-Spatial Blog post with the code being available on GitHub

ca san mateo

create a WKT layer
call spatial.addWKTLayer('geom', 'wkt')
match on all District nodes and add them to the WKT layer
MATCH (d:District)
WITH collect(d) AS districts
CALL spatial.addNodes('geom', districts) YIELD node
RETURN count(*)
Find Geometry within distance and related
WITH {latitude: 37.563440, longitude: -122.322265} AS coordinate
CALL spatial.withinDistance('geom', coordinate, 1) YIELD node AS district
MATCH (district)<-[:REPRESENTS]-(legislator:Legislator)
RETURN district.state, legislator.govtrackID, legislator.lastName, l.currentParty AS party

Semantic Web (RDF / Ontology) Procedures

Neo4j Consultant Jesus Barrasa wrote a number of procedures for importing and managing semantic web data.

import RDF formats and convert them into the property graph model
CALL semantics.importRDF(rdf-url-or-file,format, shorten-url-flag, batch-commit-size);
import ontologies into Neo4j ontologies for graph generation and checking
CALL semantics.LiteOntoImport(own-url-or-file,'RDF/XML')

screen shot 2016 06 09 at 00 45 38

You can find them here on GitHub, for more detail see his blog post series.

Developing your own Procedures and Functions

Writing your first Function

You can find details on writing and testing procedures in the Neo4j Manual.

There is even an example GitHub repository with detailed documentation and comments that you can clone directly and use as a starting point.

User-defined functions are simpler, so let’s look at one here:

  • @UserFunction annotated, named Java Methods
    • default name is class package + "." + method-name
  • take `@Name’ed parameters (with optional default values)
  • return a single value
  • are read only
  • can use @Context injected GraphDatabaseService etc
  • run within Transaction of the Cypher Statement
simple user defined uuid function
@Description("creates an UUID (universally unique id)")
public String uuid() {
   return UUID.randomUUID().toString();
use the function like this
CREATE (p:Person {id: create.uuid(), name:{name}})

Testing the Function

The Neo4j testing library neo4j-harness enables you to spin up a Neo4j server, provide fixtures for data setup and register your functions and procedures.

You then call and test test the function via the bolt – neo4j-java-driver.

public Neo4jRule neo4j = new Neo4jRule()
                         .withFunction( UUIDs.class );

try( Driver driver = GraphDatabase.driver( neo4j.boltURI() , config ) {
    Session session = driver.session();
    String uuid ="RETURN create.uuid() AS uuid")
                         .single().get( 0 ).asString();
    assertThat( uuid,....);

Writing a Procedure

User defined procedures are similar:

  • @Procedure annotated, Java methods
  • with an additional mode attribute (Read, Write, Dbms)
  • return a Stream of value objects (DTO) with public fields
  • value object fields are turned into result columns to be `YIELD`ed
Expose dijkstra algoritm from the Java API to Cypher
@Procedure(mode = Write)
@Description("apoc.algo.dijkstra(startNode, endNode, 'KNOWS', 'distance') YIELD path," +
       " weight - run dijkstra with relationship property name as cost function")
public Stream<WeightedPathResult> dijkstra(
       @Name("startNode") Node startNode,
       @Name("endNode") Node endNode,
       @Name("type") String type,
       @Name("costProperty") String costProperty) {

   PathFinder<WeightedPath> algo = GraphAlgoFactory.dijkstra(
   Iterable<WeightedPath> allPaths = algo.findAllPaths(startNode, endNode);
   return Iterables.asCollection(allPaths).stream()

public static class WeightedPathResult {
   public final Path path;
   public final double weight;
   public WeightedPathResult(WeightedPath wp) { this.path = wp; this.weight = wp.weight(); }

Use a build tool (like maven, gradle, ant) to package your code into a jar-file and copy that into $NEO4J_HOME/plugins Make sure required dependencies are added as well, either to your jar or the plugins directory.