Overview
The CALL
statement can facilitate 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 statement> ::=
[ "OPTIONAL" ] "CALL" [ "(" [ <variable list> ] ")" ] "{"
<statement block>
"}"
<variable list> ::=
<variable reference> [ { "," <variable reference> }... ]
Details
- You can import one or more variables (comma-spearated) from earlier parts of the query into
CALL
. If omitted, all variables are implicitly imported. - The operations for subqueries are defined in
<statement block>
, which can serve for various purposes such as data retrieval, modification and others. - When subqueries produce outputs with the
RETURN
statement:- Each ouput record is appended to the right side of the corresponding input record.
- If a subquery yields no record, the associated input record is discarded.
- If a subquery produces multiple output records, the corresponding input record is duplicated accordingly.
- Data modification subqueries may not contain a
RETURN
statement. In such cases, the number of records after the subqueries remain the same as before. - The
OPTIONAL
keyword can be used to handle cases where the subqueries have no returns, in which anull
value returns instead.
Example Graph
CREATE GRAPH myGraph {
NODE User ({name string}),
NODE Club (),
EDGE Follows ()-[{}]->(),
EDGE Joins ()-[{rates uint32}]->()
} PARTITION BY HASH(Crc32) SHARDS [1]
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 |
Brainy | C02 |
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 Joins
edges:
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' name
:
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 | 2 |
lionbower | 0 |
mochaeach | 0 |
purplechalk | 2 |
rowlock | 0 |