3.7.3. Combining operators

The combining operators are used to piece together other operators.

Operators:

The following graph is used for the examples below:

Figure 3.26. Graph
alt

3.7.3.1. Apply

Apply works by performing a nested loop. Every row being produced on the left-hand side of the Apply operator will be fed to the leaf operator on the right-hand side, and then Apply will yield the combined results. Apply, being a nested loop, can be seen as a warning that a better plan was not found.

Query. 

MATCH (p:Person)-[:FRIENDS_WITH]->(f)
WITH p, count(f) AS fs
WHERE fs > 2
OPTIONAL MATCH (p)-[:WORKS_IN]->(city)
RETURN city.name

Finds all the people with more than two friends and returns the city they work in.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime INTERPRETED

+----------------------+----------------+----------------------------------------------+----------------------------------------+
| Operator             | Estimated Rows | Variables                                    | Other                                  |
+----------------------+----------------+----------------------------------------------+----------------------------------------+
| +ProduceResults      |              1 | anon[70], anon[93], city, city.name, fs, p   |                                        |
| |                    +----------------+----------------------------------------------+----------------------------------------+
| +Projection          |              1 | city.name -- anon[70], anon[93], city, fs, p | {city.name : city.name}                |
| |                    +----------------+----------------------------------------------+----------------------------------------+
| +OptionalExpand(All) |              1 | anon[93], city -- anon[70], fs, p            | (p)-[:WORKS_IN]->(city)                |
| |                    +----------------+----------------------------------------------+----------------------------------------+
| +Filter              |              1 | anon[70], fs, p                              | anon[70]                               |
| |                    +----------------+----------------------------------------------+----------------------------------------+
| +Projection          |              1 | anon[70] -- fs, p                            | {p : p, fs : fs,  : fs > {  AUTOINT0}} |
| |                    +----------------+----------------------------------------------+----------------------------------------+
| +EagerAggregation    |              1 | fs -- p                                      | p                                      |
| |                    +----------------+----------------------------------------------+----------------------------------------+
| +Expand(All)         |              2 | anon[17], f -- p                             | (p)-[:FRIENDS_WITH]->(f)               |
| |                    +----------------+----------------------------------------------+----------------------------------------+
| +NodeByLabelScan     |             14 | p                                            | :Person                                |
+----------------------+----------------+----------------------------------------------+----------------------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (p:Person)-[:FRIENDS_WITH]->(f) WITH p, count(f) as fs WHERE fs > 2 OPTIONAL MATCH (p)-[:WORKS_IN]->(city) RETURN city.name

3.7.3.2. SemiApply

Tests for the existence of a pattern predicate. SemiApply takes a row from its child operator and feeds it to the leaf operator on the right-hand side. If the right-hand side operator tree yields at least one row, the row from the left-hand side is yielded by the SemiApply operator. This makes SemiApply a filtering operator, used mostly for pattern predicates in queries.

Query. 

MATCH (p:Person)
WHERE (p)-[:FRIENDS_WITH]->()
RETURN p.name

Finds all the people who have friends.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime SLOTTED

+------------------+----------------+-------------+-------------------------------------------------------+
| Operator         | Estimated Rows | Variables   | Other                                                 |
+------------------+----------------+-------------+-------------------------------------------------------+
| +ProduceResults  |              4 | p, p.name   |                                                       |
| |                +----------------+-------------+-------------------------------------------------------+
| +Projection      |              4 | p.name -- p | {p.name : p.name}                                     |
| |                +----------------+-------------+-------------------------------------------------------+
| +Filter          |              4 | p           | GetDegreePrimitive(0,Some(FRIENDS_WITH),OUTGOING) > 0 |
| |                +----------------+-------------+-------------------------------------------------------+
| +NodeByLabelScan |             14 | p           | :Person                                               |
+------------------+----------------+-------------+-------------------------------------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (p:Person) WHERE (p)-[:FRIENDS_WITH]->() RETURN p.name

3.7.3.3. AntiSemiApply

Tests for the absence of a pattern. AntiSemiApply takes a row from its child operator and feeds it to the leaf operator on the right-hand side. If the right-hand side operator tree yields at least one row, the row from the left-hand side is yielded by the AntiSemiApply operator. This makes AntiSemiApply a filtering operator, used for pattern predicates in queries.

Query. 

MATCH (me:Person { name: "me" }),(other:Person)
WHERE NOT (me)-[:FRIENDS_WITH]->(other)
RETURN other.name

Finds the names of all the people who are not my friends.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime SLOTTED

+--------------------+----------------+-------------------------+-------------------------------+
| Operator           | Estimated Rows | Variables               | Other                         |
+--------------------+----------------+-------------------------+-------------------------------+
| +ProduceResults    |              4 | me, other, other.name   |                               |
| |                  +----------------+-------------------------+-------------------------------+
| +Projection        |              4 | other.name -- me, other | {other.name : other.name}     |
| |                  +----------------+-------------------------+-------------------------------+
| +AntiSemiApply     |              4 | me, other               |                               |
| |\                 +----------------+-------------------------+-------------------------------+
| | +Expand(Into)    |              0 | anon[63] -- me, other   | (me)-[:FRIENDS_WITH]->(other) |
| | |                +----------------+-------------------------+-------------------------------+
| | +Argument        |             14 | me, other               |                               |
| |                  +----------------+-------------------------+-------------------------------+
| +CartesianProduct  |             14 | me -- other             |                               |
| |\                 +----------------+-------------------------+-------------------------------+
| | +NodeByLabelScan |             14 | other                   | :Person                       |
| |                  +----------------+-------------------------+-------------------------------+
| +NodeIndexSeek     |              1 | me                      | :Person(name)                 |
+--------------------+----------------+-------------------------+-------------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (me:Person {name: "me"}), (other:Person) WHERE NOT (me)-[:FRIENDS_WITH]->(other) RETURN other.name

3.7.3.4. LetSemiApply

Tests for the existence of a pattern predicate. When a query contains multiple pattern predicates LetSemiApply will be used to evaluate the first of these. It will record the result of evaluating the predicate but will leave any filtering to another operator.

Query. 

MATCH (other:Person)
WHERE (other)-[:FRIENDS_WITH]->() OR (other)-[:WORKS_IN]->()
RETURN other.name

Finds the names of all the people who have a friend or who work somewhere. The LetSemiApply operator will be used to check for the existence of the FRIENDS_WITH relationship from each person.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime SLOTTED

+------------------+----------------+---------------------+--------------------------------------------------------------------------------------------------------------+
| Operator         | Estimated Rows | Variables           | Other                                                                                                        |
+------------------+----------------+---------------------+--------------------------------------------------------------------------------------------------------------+
| +ProduceResults  |              7 | other, other.name   |                                                                                                              |
| |                +----------------+---------------------+--------------------------------------------------------------------------------------------------------------+
| +Projection      |              7 | other.name -- other | {other.name : other.name}                                                                                    |
| |                +----------------+---------------------+--------------------------------------------------------------------------------------------------------------+
| +Filter          |              7 | other               | OR( GetDegreePrimitive(0,Some(FRIENDS_WITH),OUTGOING) > 0, GetDegreePrimitive(0,Some(WORKS_IN),OUTGOING) > 0 |
| |                +----------------+---------------------+--------------------------------------------------------------------------------------------------------------+
| +NodeByLabelScan |             14 | other               | :Person                                                                                                      |
+------------------+----------------+---------------------+--------------------------------------------------------------------------------------------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (other:Person) WHERE (other)-[:FRIENDS_WITH]->() OR (other)-[:WORKS_IN]->() RETURN other.name

3.7.3.5. LetAntiSemiApply

Tests for the absence of a pattern. When a query contains multiple pattern predicates LetAntiSemiApply will be used to evaluate the first of these. It will record the result of evaluating the predicate but will leave any filtering to another operator. The following query will find all the people who don’t have any friends or who work somewhere.

Query. 

MATCH (other:Person)
WHERE NOT ((other)-[:FRIENDS_WITH]->()) OR (other)-[:WORKS_IN]->()
RETURN other.name

Finds all the people who don’t have any friends or who work somewhere. The LetAntiSemiApply operator will be used to check for the absence of the FRIENDS_WITH relationship from each person.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime SLOTTED

+------------------+----------------+---------------------+---------------------------------------------------------------------------------------------------------------+
| Operator         | Estimated Rows | Variables           | Other                                                                                                         |
+------------------+----------------+---------------------+---------------------------------------------------------------------------------------------------------------+
| +ProduceResults  |              7 | other, other.name   |                                                                                                               |
| |                +----------------+---------------------+---------------------------------------------------------------------------------------------------------------+
| +Projection      |              7 | other.name -- other | {other.name : other.name}                                                                                     |
| |                +----------------+---------------------+---------------------------------------------------------------------------------------------------------------+
| +Filter          |              7 | other               | OR( GetDegreePrimitive(0,Some(FRIENDS_WITH),OUTGOING) <= 0, GetDegreePrimitive(0,Some(WORKS_IN),OUTGOING) > 0 |
| |                +----------------+---------------------+---------------------------------------------------------------------------------------------------------------+
| +NodeByLabelScan |             14 | other               | :Person                                                                                                       |
+------------------+----------------+---------------------+---------------------------------------------------------------------------------------------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (other:Person) WHERE NOT((other)-[:FRIENDS_WITH]->()) OR (other)-[:WORKS_IN]->() RETURN other.name

3.7.3.6. SelectOrSemiApply

Tests for the existence of a pattern predicate and evaluates a predicate. This operator allows for the mixing of normal predicates and pattern predicates that check for the existence of a pattern. First the normal expression predicate is evaluated, and only if it returns false the costly pattern predicate evaluation is performed.

Query. 

MATCH (other:Person)
WHERE other.age > 25 OR (other)-[:FRIENDS_WITH]->()
RETURN other.name

Finds the names of all people who have friends, or are older than '25'.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime SLOTTED

+------------------+----------------+---------------------+-------------------------------------------------------------------------------------+
| Operator         | Estimated Rows | Variables           | Other                                                                               |
+------------------+----------------+---------------------+-------------------------------------------------------------------------------------+
| +ProduceResults  |              4 | other, other.name   |                                                                                     |
| |                +----------------+---------------------+-------------------------------------------------------------------------------------+
| +Projection      |              4 | other.name -- other | {other.name : other.name}                                                           |
| |                +----------------+---------------------+-------------------------------------------------------------------------------------+
| +Filter          |              4 | other               | OR( other.age > {  AUTOINT0}, GetDegreePrimitive(0,Some(FRIENDS_WITH),OUTGOING) > 0 |
| |                +----------------+---------------------+-------------------------------------------------------------------------------------+
| +NodeByLabelScan |             14 | other               | :Person                                                                             |
+------------------+----------------+---------------------+-------------------------------------------------------------------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (other:Person) WHERE other.age > 25 OR (other)-[:FRIENDS_WITH]->() RETURN other.name

3.7.3.7. SelectOrAntiSemiApply

Tests for the absence of a pattern predicate and evaluates a predicate.

Query. 

MATCH (other:Person)
WHERE other.age > 25 OR NOT (other)-[:FRIENDS_WITH]->()
RETURN other.name

Finds the names of all people who do not have friends, or are older than '25'.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime SLOTTED

+------------------+----------------+---------------------+--------------------------------------------------------------------------------------+
| Operator         | Estimated Rows | Variables           | Other                                                                                |
+------------------+----------------+---------------------+--------------------------------------------------------------------------------------+
| +ProduceResults  |              4 | other, other.name   |                                                                                      |
| |                +----------------+---------------------+--------------------------------------------------------------------------------------+
| +Projection      |              4 | other.name -- other | {other.name : other.name}                                                            |
| |                +----------------+---------------------+--------------------------------------------------------------------------------------+
| +Filter          |              4 | other               | OR( other.age > {  AUTOINT0}, GetDegreePrimitive(0,Some(FRIENDS_WITH),OUTGOING) <= 0 |
| |                +----------------+---------------------+--------------------------------------------------------------------------------------+
| +NodeByLabelScan |             14 | other               | :Person                                                                              |
+------------------+----------------+---------------------+--------------------------------------------------------------------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (other:Person) WHERE other.age > 25 OR NOT (other)-[:FRIENDS_WITH]->() RETURN other.name

3.7.3.8. ConditionalApply

Checks whether a variable is not null, and if so the right-hand side will be executed.

Query. 

MERGE (p:Person { name: 'Andres' })
ON MATCH SET p.exists = TRUE

Looks for the existence of a person called 'Andres', and if found sets the exists property to true.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime INTERPRETED

+-----------------------+----------------+-----------+---------------+
| Operator              | Estimated Rows | Variables | Other         |
+-----------------------+----------------+-----------+---------------+
| +ProduceResults       |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +EmptyResult          |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +AntiConditionalApply |              1 | p         |               |
| |\                    +----------------+-----------+---------------+
| | +MergeCreateNode    |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +ConditionalApply     |              1 | p         |               |
| |\                    +----------------+-----------+---------------+
| | +SetProperty        |              1 | p         |               |
| | |                   +----------------+-----------+---------------+
| | +Argument           |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +Optional             |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +NodeIndexSeek        |              1 | p         | :Person(name) |
+-----------------------+----------------+-----------+---------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MERGE (p:Person {name: 'Andres'}) ON MATCH SET p.exists = true

3.7.3.9. AntiConditionalApply

Checks whether a variable is null, and if so the right-hand side will be executed.

Query. 

MERGE (p:Person { name: 'Andres' })
ON CREATE SET p.exists = TRUE

Looks for the existence of a person called 'Andres', and if not found, creates one and sets the exists property to true.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime INTERPRETED

+-----------------------+----------------+-----------+---------------+
| Operator              | Estimated Rows | Variables | Other         |
+-----------------------+----------------+-----------+---------------+
| +ProduceResults       |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +EmptyResult          |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +AntiConditionalApply |              1 | p         |               |
| |\                    +----------------+-----------+---------------+
| | +SetProperty        |              1 | p         |               |
| | |                   +----------------+-----------+---------------+
| | +MergeCreateNode    |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +Optional             |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +NodeIndexSeek        |              1 | p         | :Person(name) |
+-----------------------+----------------+-----------+---------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MERGE (p:Person {name: 'Andres'}) ON CREATE SET p.exists = true

3.7.3.10. AssertSameNode

This operator is used to ensure that no uniqueness constraints are violated.

Query. 

MERGE (t:Team { name: 'Engineering', id: 42 })

Looks for the existence of a team with the supplied name and id, and if one does not exist, it will be created. Owing to the existence of two uniqueness constraints on :Team(name) and :Team(id), any node that would be found by the UniqueIndexSeek must be the very same node, or the constraints would be violated.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime INTERPRETED

+---------------------------------+----------------+-----------+-------------+
| Operator                        | Estimated Rows | Variables | Other       |
+---------------------------------+----------------+-----------+-------------+
| +ProduceResults                 |              1 | t         |             |
| |                               +----------------+-----------+-------------+
| +EmptyResult                    |              1 | t         |             |
| |                               +----------------+-----------+-------------+
| +AntiConditionalApply           |              1 | t         |             |
| |\                              +----------------+-----------+-------------+
| | +MergeCreateNode              |              1 | t         |             |
| |                               +----------------+-----------+-------------+
| +Optional                       |              1 | t         |             |
| |                               +----------------+-----------+-------------+
| +AssertSameNode                 |              0 | t         |             |
| |\                              +----------------+-----------+-------------+
| | +NodeUniqueIndexSeek(Locking) |              1 | t         | :Team(name) |
| |                               +----------------+-----------+-------------+
| +NodeUniqueIndexSeek(Locking)   |              1 | t         | :Team(id)   |
+---------------------------------+----------------+-----------+-------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MERGE (t:Team {name: 'Engineering', id: 42})

3.7.3.11. NodeHashJoin

Using a hash table, a NodeHashJoin joins the input coming from the left with the input coming from the right.

Query. 

MATCH (andy:Person { name:'Andreas' })-[:WORKS_IN]->(loc)<-[:WORKS_IN]-(matt:Person { name:'Mattis' })
RETURN loc.name

Returns the name of the location where the matched persons both work.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime COMPILED

+------------------+----------------+-------------------------------------------------+---------------------------+
| Operator         | Estimated Rows | Variables                                       | Other                     |
+------------------+----------------+-------------------------------------------------+---------------------------+
| +ProduceResults  |             10 | anon[39], anon[58], andy, loc, loc.name, matt   |                           |
| |                +----------------+-------------------------------------------------+---------------------------+
| +Projection      |             10 | loc.name -- anon[39], anon[58], andy, loc, matt | {loc.name : loc.name}     |
| |                +----------------+-------------------------------------------------+---------------------------+
| +Filter          |             10 | anon[39], anon[58], andy, loc, matt             | NOT(anon[39] = anon[58])  |
| |                +----------------+-------------------------------------------------+---------------------------+
| +NodeHashJoin    |             10 | anon[39], andy -- anon[58], loc, matt           | loc                       |
| |\               +----------------+-------------------------------------------------+---------------------------+
| | +Expand(All)   |             19 | anon[58], loc -- matt                           | (matt)-[:WORKS_IN]->(loc) |
| | |              +----------------+-------------------------------------------------+---------------------------+
| | +NodeIndexSeek |              1 | matt                                            | :Person(name)             |
| |                +----------------+-------------------------------------------------+---------------------------+
| +Expand(All)     |             19 | anon[39], loc -- andy                           | (andy)-[:WORKS_IN]->(loc) |
| |                +----------------+-------------------------------------------------+---------------------------+
| +NodeIndexSeek   |              1 | andy                                            | :Person(name)             |
+------------------+----------------+-------------------------------------------------+---------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (london:Location {name: 'London'}), (person:Person {name: 'Pontus'}) FOREACH(x in range(0,250) | CREATE (person)-[:WORKS_IN]->(london) ) MATCH (andy:Person {name:'Andreas'})-[:WORKS_IN]->(loc)<-[:WORKS_IN]-(matt:Person {name:'Mattis'}) RETURN loc.name

3.7.3.12. Triadic

Triadic is used to solve triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. It does so by putting all the friends in a set, and use that set to check if the friend-of-friends are already connected to me.

Query. 

MATCH (me:Person)-[:FRIENDS_WITH]-()-[:FRIENDS_WITH]-(other)
WHERE NOT (me)-[:FRIENDS_WITH]-(other)
RETURN other.name

Finds the names of all friends of my friends that are not already my friends.

Query plan. 

Compiler CYPHER 3.3

Planner COST

Runtime INTERPRETED

+-------------------+----------------+-------------------------------------------------------+----------------------------+
| Operator          | Estimated Rows | Variables                                             | Other                      |
+-------------------+----------------+-------------------------------------------------------+----------------------------+
| +ProduceResults   |              0 | anon[18], anon[35], anon[37], me, other, other.name   |                            |
| |                 +----------------+-------------------------------------------------------+----------------------------+
| +Projection       |              0 | other.name -- anon[18], anon[35], anon[37], me, other | {other.name : other.name}  |
| |                 +----------------+-------------------------------------------------------+----------------------------+
| +TriadicSelection |              0 | anon[18], anon[35], anon[37], me, other               | me, anon[35], other        |
| |\                +----------------+-------------------------------------------------------+----------------------------+
| | +Filter         |              0 | anon[18], anon[35], anon[37], me, other               | NOT(anon[18] = anon[37])   |
| | |               +----------------+-------------------------------------------------------+----------------------------+
| | +Expand(All)    |              0 | anon[37], other -- anon[18], anon[35], me             | ()-[:FRIENDS_WITH]-(other) |
| | |               +----------------+-------------------------------------------------------+----------------------------+
| | +Argument       |              4 | anon[18], anon[35], me                                |                            |
| |                 +----------------+-------------------------------------------------------+----------------------------+
| +Expand(All)      |              4 | anon[18], anon[35] -- me                              | (me)-[:FRIENDS_WITH]-()    |
| |                 +----------------+-------------------------------------------------------+----------------------------+
| +NodeByLabelScan  |             14 | me                                                    | :Person                    |
+-------------------+----------------+-------------------------------------------------------+----------------------------+

Total database accesses: ?

Try this query live.  CREATE CONSTRAINT ON (team:Team) ASSERT team.name is UNIQUE CREATE CONSTRAINT ON (team:Team) ASSERT team.id is UNIQUE CREATE INDEX ON :Location(name) CREATE INDEX ON :Person(name) CREATE (me:Person {name:'me'}) CREATE (andres:Person {name:'Andres'}) CREATE (andreas:Person {name:'Andreas'}) CREATE (mattias:Person {name:'Mattias'}) CREATE (lovis:Person {name:'Lovis'}) CREATE (pontus:Person {name:'Pontus'}) CREATE (max:Person {name:'Max'}) CREATE (konstantin:Person {name:'Konstantin'}) CREATE (stefan:Person {name:'Stefan'}) CREATE (mats:Person {name:'Mats'}) CREATE (petra:Person {name:'Petra'}) CREATE (craig:Person {name:'Craig'}) CREATE (steven:Person {name:'Steven'}) CREATE (chris:Person {name:'Chris'}) CREATE (london:Location {name:'London'}) CREATE (malmo:Location {name:'Malmo'}) CREATE (sf:Location {name:'San Francisco'}) CREATE (berlin:Location {name:'Berlin'}) CREATE (newyork:Location {name:'New York'}) CREATE (kuala:Location {name:'Kuala Lumpur'}) CREATE (stockholm:Location {name:'Stockholm'}) CREATE (paris:Location {name:'Paris'}) CREATE (madrid:Location {name:'Madrid'}) CREATE (rome:Location {name:'Rome'}) CREATE (england:Country {name:'England'}) CREATE (field:Team {name:'Field'}) CREATE (engineering:Team {name:'Engineering', id: 42}) CREATE (sales:Team {name:'Sales'}) CREATE (monads:Team {name:'Team Monads'}) CREATE (birds:Team {name:'Team Enlightened Birdmen'}) CREATE (quality:Team {name:'Team Quality'}) CREATE (rassilon:Team {name:'Team Rassilon'}) CREATE (executive:Team {name:'Team Executive'}) CREATE (remoting:Team {name:'Team Remoting'}) CREATE (other:Team {name:'Other'}) CREATE (me)-[:WORKS_IN {duration: 190}]->(london) CREATE (andreas)-[:WORKS_IN {duration: 187}]->(london) CREATE (andres)-[:WORKS_IN {duration: 150}]->(london) CREATE (mattias)-[:WORKS_IN {duration: 230}]->(london) CREATE (lovis)-[:WORKS_IN {duration: 230}]->(sf) CREATE (pontus)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (max)-[:WORKS_IN {duration: 230}]->(newyork) CREATE (konstantin)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(london) CREATE (stefan)-[:WORKS_IN {duration: 230}]->(berlin) CREATE (mats)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (petra)-[:WORKS_IN {duration: 230}]->(london) CREATE (craig)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (steven)-[:WORKS_IN {duration: 230}]->(malmo) CREATE (chris)-[:WORKS_IN {duration: 230}]->(madrid) CREATE (london)-[:IN]->(england) CREATE (me)-[:FRIENDS_WITH]->(andres) CREATE (andres)-[:FRIENDS_WITH]->(andreas) MATCH (me:Person)-[:FRIENDS_WITH]-()-[:FRIENDS_WITH]-(other) WHERE NOT (me)-[:FRIENDS_WITH]-(other) RETURN other.name