User Defined Procedures and Functions
This guide explains how to use, create and deploy user defined procedures and functions, the extension mechanism of Cypher, Neo4j’s query language. It also covers existing, widely used procedure libraries
You should have learned to read and write statements in Cypher and seen the need for additional capabilities.
Intermediate
Extending Cypher
Cypher is a quite powerful and expressive language, with first class graph pattern and collection support. But sometimes you need to do more than it currently offers, like additional graph algorithms, parallelization or custom conversions.
That’s why Neo4j and Cypher can be extended with User Defined Procedures and Functions. Neo4j itself provides and utilizes custom procedures. Many of the monitoring, introspection and security features exposed by Neo4j-Browser are implemented using procedures.
What are Procedures and Functions?
-
Functions are simple computations / conversions and return a single value
-
Functions can be used in any expression or predicate
-
Procedures are more complex operations and generate streams of results.
-
Procedures must be used within the
CALL
clause andYIELD
their result columns -
They can generate, fetch or compute data to make it available to later processing steps in your Cypher query
Listing & Using Functions and Procedures
There are a number of built in procedures, two of which are used to list available functions and procedures.
Run the following statements along to get a hang of the usage and see their results.
CALL dbms.procedures()
Call dbms.functions()
to list functions.
Each procedure returns one or more columns of data.
With yield
these columns can be selected and also aliased and are then available in your Cypher statement.
CALL dbms.procedures()
YIELD name, signature, description as text
WHERE name STARTS WITH 'db.'
RETURN * ORDER BY name ASC
Of course you can also process the result columns with other Cypher clauses. Here we group them by package.
CALL dbms.procedures()
YIELD name, signature, description
WITH split(name,".") AS parts
RETURN parts[0..-1] AS package, count(*) AS count,
collect(parts[-1]) AS names
ORDER BY count DESC
package | count | names |
---|---|---|
["dbms","security"] |
16 |
["activateUser","addRoleToUser","changePassword",….] |
["apoc","refactor"] |
11 |
["categorize","cloneNodes","from"….] |
["apoc","load"] |
9 |
["csv","driver","jdbc","jdbcParams","json","jsoe"] |
["db"] |
9 |
["awaitIndex","constraints","indexes","labels",..,"schema"] |
["dbms"] |
9 |
["components","functions","queries","procedures",…] |
As of Neo4j 3.1, all functions available are directly part of the Cypher implementation, so User Defined Functions would only come from installed libraries.
You can take any procedure library and deploy it to your server to make additional procedures and functions available.
Please also have a look at the procedure section in the Neo4j Manual.
Deploying Procedures & Functions
If you built your own procedures or downloaded them from an community project, they are packaged in a jar-file.
You can copy that file into the $NEO4J_HOME/plugins
directory of your Neo4j server and restart.
A word of caution. As procedures and functions use the low level Java API they can access all Neo4j internals as well as the file system and machine. That’s why you should know which procedures you deploy and why. Only install procedures from trusted sources. If they are open source, check their source-code and best build them yourself. |
Certain procedures and functions are available for self-managed Neo4j Enterprise Edition and Community Edition. Custom code described in this section is not compatible with AuraDB |
Procedure and Function Gallery
In our Neo4j Labs projects, we provide an impressive set of libraries built by our community and staff. Check it out to see what’s already there. Many of your needs will already be covered by those, for example:
-
index operations
-
database/api integration
-
graph refactorings
-
import and export
-
spatial index lookup
-
rdf import and export
-
and many more
Here are two cool examples of what you can do:
A procedure to load data from another database:
WITH "jdbc:mysql://localhost:3306/northwind?user=root" as url
CALL apoc.load.jdbc(url,"products") YIELD row
RETURN row
ORDER BY row.UnitPrice DESC
LIMIT 20
Functions to format and parse timestamps of different resolutions:
RETURN apoc.date.format(timestamp()) as time,
apoc.date.format(timestamp(),'ms','yyyy-MM-dd') as date,
apoc.date.parse('13.01.1975','s','dd.MM.yyyy') as unixtime,
apoc.date.parse('2017-01-05 13:03:07') as millis
time | date | unixtime | millis |
---|---|---|---|
"2017-01-05 13:06:39" |
"2017-01-05" |
158803200 |
1483621387000 |
Developing your own Procedures and Functions
You can find details on writing and testing procedures in the Neo4j Manual. The example GitHub repository contains detailed documentation and comments that you can clone directly and use as a starting point.
Here are just some initial tips:
User-defined functions are simpler, so let’s start with them:
-
@UserFunction
are annotated, public Java methods in a class -
their default name is package-name.method-name
-
they return a single value
-
are read only
User defined procedures are similar:
-
@Procedure
annotated, Java methods -
with an additional
mode
attribute (READ, WRITE, DBMS
) -
return a Java 8
Stream
of simple objects withpublic
fields -
these fields names are turned into result columns available for
YIELD
These things are valid for both:
-
take
@Name
annotated parameters (with optional default values) -
can use an injected
@Context public GraphDatabaseService
-
run within transaction of the Cypher statement
-
supported types for parameters and results are:
Long, Double, Boolean, String, Node, Relationship, Path, Object
Are you struggling?
If you need help with any of the information contained on this page, you can reach out to other members of our community.
You can ask questions in the Cypher category on the Neo4j Community Site.
|
Was this page helpful?