3.3.17. CALL

The CALL clause is used to call a procedure deployed in the database.

3.3.17.1. Introduction

Procedures are called using the CALL clause.

Each procedure call needs to specify all required procedure arguments. This may be done either explicitly, by using a comma-separated list wrapped in parentheses after the procedure name, or implicitly by using available query parameters as procedure call arguments. The latter form is available only in a so-called standalone procedure call, when the whole query consists of a single CALL clause.

Most procedures return a stream of records with a fixed set of result fields, similar to how running a Cypher query returns a stream of records. The YIELD sub-clause is used to explicitly select which of the available result fields are returned as newly-bound variables from the procedure call to the user or for further processing by the remaining query. Each yielded result field may optionally be renamed using aliasing (i.e. resultFieldName AS newName). All new variables bound by a procedure call are added to the set of variables already bound in the current scope. It is an error if a procedure call tries to rebind a previously bound variable (i.e. a procedure call cannot shadow a variable that was previously bound in the current scope).

Inside a larger query, the records returned from a procedure call with an explicit YIELD may be further filtered using a WHERE sub-clause followed by a predicate (similar to WITH …​ WHERE …​).

If the called procedure declares at least one result field, YIELD may generally not be omitted. However YIELD may always be omitted in a standalone procedure call. In this case, all result fields are yielded as newly-bound variables from the procedure call to the user.

Neo4j supports the notion of VOID procedures. A VOID procedure is a procedure that does not declare any result fields and returns no result records and that has explicitly been declared as VOID. Calling a VOID procedure may only have a side effect and thus does neither allow nor require the use of YIELD. Calling a VOID procedure in the middle of a larger query will simply pass on each input record (i.e. it acts like WITH * in terms of the record stream).

The following examples show how to pass arguments to and yield result fields from a procedure call. All examples use the following procedure:

public class IndexingProcedure
{
    @Context
    public GraphDatabaseService db;

    /**
     * Adds a node to a named legacy index. Useful to, for instance, update
     * a full-text index through cypher.
     * @param indexName the name of the index in question
     * @param nodeId id of the node to add to the index
     * @param propKey property to index (value is read from the node)
     */
    @Procedure(mode = Mode.WRITE)
    public void addNodeToIndex( @Name("indexName") String indexName,
                                @Name("node") long nodeId,
                                @Name( value = "propKey", defaultValue = "name" ) String propKey )
    {
        Node node = db.getNodeById( nodeId );
        db.index()
          .forNodes( indexName )
          .add( node, propKey, node.getProperty( propKey ) );
    }
}

This clause cannot be combined with other clauses.

3.3.17.2. Call a procedure

This calls the built-in procedure db.labels, which lists all labels used in the database.

Query. 

CALL db.labels

Result. 

+-----------------+
| label           |
+-----------------+
| "User"          |
| "Administrator" |
+-----------------+
2 rows

3.3.17.3. Call a procedure using a quoted namespace and name

This calls the built-in procedure db.labels, which lists all labels used in the database.

Query. 

CALL `db`.`labels`

Result. 

+-----------------+
| label           |
+-----------------+
| "User"          |
| "Administrator" |
+-----------------+
2 rows

3.3.17.4. Call a procedure with literal arguments

This calls the example procedure org.neo4j.procedure.example.addNodeToIndex using literal arguments, i.e. arguments that are written out directly in the statement text.

Query. 

CALL org.neo4j.procedure.example.addNodeToIndex('users', 0, 'name')

Since our example procedure does not return any result, the result is empty.

Result. 

+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+

3.3.17.5. Call a procedure with parameter arguments

This calls the example procedure org.neo4j.procedure.example.addNodeToIndex using parameters as arguments. Each procedure argument is taken to be the value of a corresponding statement parameters with the same name (or null if no such parameter has been given).

Parameters. 

{
  "indexName" : "users",
  "node" : 0,
  "propKey" : "name"
}

Query. 

CALL org.neo4j.procedure.example.addNodeToIndex

Since our example procedure does not return any result, the result is empty.

Result. 

+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+

3.3.17.6. Call a procedure with mixed literal and parameter arguments

This calls the example procedure org.neo4j.procedure.example.addNodeToIndex using both literal and parameter arguments.

Parameters. 

{
  "node" : 0
}

Query. 

CALL org.neo4j.procedure.example.addNodeToIndex('users', $node, 'name')

Since our example procedure does not return any result, the result is empty.

Result. 

+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+

3.3.17.7. Call a procedure with literal and default arguments

This calls the example procedure org.neo4j.procedure.example.addNodeToIndex using literal arguments, i.e. arguments that are written out directly in the statement text, and a trailing default argument that is provided by the procedure itself.

Query. 

CALL org.neo4j.procedure.example.addNodeToIndex('users', 0)

Since our example procedure does not return any result, the result is empty.

Result. 

+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+

3.3.17.8. Call a procedure within a complex query

This calls the built-in procedure db.labels to count all labels used in the database.

Query. 

CALL db.labels() YIELD label
RETURN count(label) AS numLabels

Since the procedure call is part of a larger query, all outputs must be named explicitly.

Result. 

+-----------+
| numLabels |
+-----------+
| 2         |
+-----------+
1 row

3.3.17.9. Call a procedure and filter its results

This calls the built-in procedure db.labels to count all in-use labels in the database that contain the word 'User'

Query. 

CALL db.labels() YIELD label
WHERE label CONTAINS 'User'
RETURN count(label) AS numLabels

Since the procedure call is part of a larger query, all outputs must be named explicitly.

Result. 

+-----------+
| numLabels |
+-----------+
| 1         |
+-----------+
1 row

3.3.17.10. Call a procedure within a complex query and rename its outputs

This calls the built-in procedure db.propertyKeys as part of counting the number of nodes per property key that is currently used in the database.

Query. 

CALL db.propertyKeys() YIELD propertyKey AS prop
MATCH (n)
WHERE n[prop] IS NOT NULL RETURN prop, count(n) AS numNodes

Since the procedure call is part of a larger query, all outputs must be named explicitly.

Result. 

+-------------------+
| prop   | numNodes |
+-------------------+
| "name" | 1        |
+-------------------+
1 row