Overview
The CALL
statement can invoke subqueries, executing each subquery using one record from the imported variables at a time. The CALL
subqueries enhance efficiency by better managing resources, particularly when working with large datasets, thus reducing memory overhead.
<call subqueries statement> ::=
[ "OPTIONAL" ] "CALL (" [ <variable list> ] ") {"
<statement block>
"}"
Details
- You can include one or more variables (spearated by commas) from earlier parts of the query in the
<variable list>
, which will be imported intoCALL
. If not specified, all available variables are implicitly imported. - The operations for subqueries are defined in the
<statement block>
, which can serve for various purposes such as data retrieval, modification and other processing tasks. - When subqueries produce outputs with the
RETURN
statement, each ouput row is appended to the right side of the corresponding input row. If a subquery yields no output, the associated input row is discarded. If a subquery produces multiple output rows, the corresponding input row is duplicated for each output row, allowing the results to be concatenated accordingly. - Data modification subqueries may not contain a
RETURN
statement. In such cases, the number of rows after the subqueries remain the same as before. - The
OPTIONAL
keyword can be used to handle cases where the subqueries have empty returns, in which anull
value will return instead.
Example Graph
The following examples run against this graph:
To create this graph, run the following query against an empty graph:
INSERT (rowlock:User {_id:'U01', name:'rowlock'}),
(brainy:User {_id:'U02', name:'Brainy'}),
(purplechalk:User {_id:'U03', name:'purplechalk'}),
(mochaeach:User {_id:'U04', name:'mochaeach'}),
(lionbower:User {_id:'U05', name:'lionbower'}),
(c01:Club {_id:'C01'}),
(c02:Club {_id:'C02'}),
(rowlock)-[:Follows]->(brainy),
(mochaeach)-[:Follows]->(brainy),
(brainy)-[:Follows]->(purplechalk),
(lionbower)-[:Follows]->(purplechalk),
(brainy)-[:Joins]->(c01),
(lionbower)-[:Joins]->(c01),
(brainy)-[:Joins]->(c02),
(mochaeach)-[:Joins]->(c02)
Queries
To find the clubs joined by each user:
MATCH (u:User)
CALL (u) {
MATCH (u)-[:Joins]-(c:Club)
RETURN c
}
RETURN u.name, c._id
Result:
u.name | c._id |
---|---|
mochaeach | C02 |
Brainy | C01 |
lionbower | C01 |
Aggregations
To count the number of followers for each user who joins a club:
MATCH (u:User)-[:Joins]-(c:Club)
CALL (u) {
MATCH (u)<-[:Follows]-(follower)
RETURN COUNT(follower) AS followersNo
}
RETURN u.name, c._id, followersNo
Result:
u.name | c._id | followersNo |
---|---|---|
mochaeach | C02 | 0 |
Brainy | C01 | 2 |
Brainy | C02 | 2 |
lionbower | C01 | 0 |
Data Modifications
To set values for the property rates
of edges labeled Joins
:
FOR score IN [1,2,3,4]
CALL (score) {
MATCH ()-[e:Joins WHERE e.rates IS NULL]-() LIMIT 1
SET e.rates = score
RETURN e
}
RETURN e
Result: e
_uuid |
_from |
_to |
_from_uuid |
_to_uuid |
schema |
values |
---|---|---|---|---|---|---|
Sys-gen | U04 | C02 | UUID of U04 | UUID of C02 | Joins | {rates: 1} |
Sys-gen | U02 | C01 | UUID of U02 | UUID of C01 | Joins | {rates: 2} |
Sys-gen | U02 | C02 | UUID of U02 | UUID of C02 | Joins | {rates: 3} |
Sys-gen | U05 | C01 | UUID of U05 | UUID of C01 | Joins | {rates: 4} |
Importing Multiple Variables
To check if any two users connected by a @Follows
edge have joined the same club:
MATCH (u1:User)<-[:Follows]-(u2:User)
CALL (u1, u2) {
OPTIONAL MATCH p = (u1)-(:Club)-(u2)
RETURN p
}
RETURN u1.name, u2.name,
CASE WHEN p IS NOT NULL THEN "Y"
ELSE "N" END AS sameClub
Result:
u1.name | u2.name | sameClub |
---|---|---|
Brainy | rowlock | N |
Brainy | mochaeach | Y |
purplechalk | Brainy | N |
purplechalk | lionbower | N |
Execution Order of Subqueries
The order in which the subquery executed is not predetermined. If a specific execution order is desired, the ORDER BY
clause should be used before CALL
to enforce that sequence.
This query counts the number of followers for each user. The execution order of the subqueries is determined by the ascending order of the users' names:
MATCH (u:User)
ORDER BY u.name
CALL (u) {
MATCH (u)<-[:Follows]-(follower)
RETURN COUNT(follower) AS followersNo
}
RETURN u.name, followersNo
Result:
u.name | followersNo |
---|---|
Brainy | 3 |
lionbower | 0 |
mochaeach | 0 |
purplechalk | 2 |
rowlock | 0 |