16.3. Combining operators

The combining operators are used to piece together other operators.

The following graph is used for the examples below:

Figure 16.1. Graph

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 

+----------------------+----------------+----------------------------------------------+--------------------------+
| Operator             | Estimated Rows | Variables                                    | Other                    |
+----------------------+----------------+----------------------------------------------+--------------------------+
| +ProduceResults      |              1 | city.name                                    | city.name                |
| |                    +----------------+----------------------------------------------+--------------------------+
| +Projection          |              1 | city.name -- anon[70], anon[93], city, fs, p | 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; 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

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 

+------------------+----------------+-------------------------+-------------------------+
| Operator         | Estimated Rows | Variables               | Other                   |
+------------------+----------------+-------------------------+-------------------------+
| +ProduceResults  |             11 | p.name                  | p.name                  |
| |                +----------------+-------------------------+-------------------------+
| +Projection      |             11 | p.name -- p             | p.name                  |
| |                +----------------+-------------------------+-------------------------+
| +SemiApply       |             11 | p                       |                         |
| |\               +----------------+-------------------------+-------------------------+
| | +Expand(All)   |              2 | anon[27], anon[45] -- p | (p)-[:FRIENDS_WITH]->() |
| | |              +----------------+-------------------------+-------------------------+
| | +Argument      |             14 | p                       |                         |
| |                +----------------+-------------------------+-------------------------+
| +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

AntiSemiApply

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 (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 

+--------------------+----------------+-------------------------+-------------------------------+
| Operator           | Estimated Rows | Variables               | Other                         |
+--------------------+----------------+-------------------------+-------------------------------+
| +ProduceResults    |              4 | other.name              | other.name                    |
| |                  +----------------+-------------------------+-------------------------------+
| +Projection        |              4 | other.name -- me, other | other.name                    |
| |                  +----------------+-------------------------+-------------------------------+
| +AntiSemiApply     |              4 | me, other               |                               |
| |\                 +----------------+-------------------------+-------------------------------+
| | +Expand(Into)    |              0 | anon[62] -- 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

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 a 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 

+--------------------+----------------+-------------------------------+-----------------------------+
| Operator           | Estimated Rows | Variables                     | Other                       |
+--------------------+----------------+-------------------------------+-----------------------------+
| +ProduceResults    |             13 | other.name                    | other.name                  |
| |                  +----------------+-------------------------------+-----------------------------+
| +Projection        |             13 | other.name -- anon[27], other | other.name                  |
| |                  +----------------+-------------------------------+-----------------------------+
| +SelectOrSemiApply |             13 | anon[27] -- other             | anon[27]                    |
| |\                 +----------------+-------------------------------+-----------------------------+
| | +Expand(All)     |             15 | anon[66], anon[80] -- other   | (other)-[:WORKS_IN]->()     |
| | |                +----------------+-------------------------------+-----------------------------+
| | +Argument        |             14 | other                         |                             |
| |                  +----------------+-------------------------------+-----------------------------+
| +LetSemiApply      |             14 | anon[27] -- other             |                             |
| |\                 +----------------+-------------------------------+-----------------------------+
| | +Expand(All)     |              2 | anon[35], anon[53] -- other   | (other)-[:FRIENDS_WITH]->() |
| | |                +----------------+-------------------------------+-----------------------------+
| | +Argument        |             14 | other                         |                             |
| |                  +----------------+-------------------------------+-----------------------------+
| +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

LetAntiSemiApply

Tests for the absence of a pattern predicate. 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 

+--------------------+----------------+-------------------------------+-----------------------------+
| Operator           | Estimated Rows | Variables                     | Other                       |
+--------------------+----------------+-------------------------------+-----------------------------+
| +ProduceResults    |             11 | other.name                    | other.name                  |
| |                  +----------------+-------------------------------+-----------------------------+
| +Projection        |             11 | other.name -- anon[31], other | other.name                  |
| |                  +----------------+-------------------------------+-----------------------------+
| +SelectOrSemiApply |             11 | anon[31] -- other             | anon[31]                    |
| |\                 +----------------+-------------------------------+-----------------------------+
| | +Expand(All)     |             15 | anon[71], anon[85] -- other   | (other)-[:WORKS_IN]->()     |
| | |                +----------------+-------------------------------+-----------------------------+
| | +Argument        |             14 | other                         |                             |
| |                  +----------------+-------------------------------+-----------------------------+
| +LetAntiSemiApply  |             14 | anon[31] -- other             |                             |
| |\                 +----------------+-------------------------------+-----------------------------+
| | +Expand(All)     |              2 | anon[39], anon[57] -- other   | (other)-[:FRIENDS_WITH]->() |
| | |                +----------------+-------------------------------+-----------------------------+
| | +Argument        |             14 | other                         |                             |
| |                  +----------------+-------------------------------+-----------------------------+
| +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

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 

+--------------------+----------------+-----------------------------+-----------------------------+
| Operator           | Estimated Rows | Variables                   | Other                       |
+--------------------+----------------+-----------------------------+-----------------------------+
| +ProduceResults    |             11 | other.name                  | other.name                  |
| |                  +----------------+-----------------------------+-----------------------------+
| +Projection        |             11 | other.name -- other         | other.name                  |
| |                  +----------------+-----------------------------+-----------------------------+
| +SelectOrSemiApply |             11 | other                       | other.age > {  AUTOINT0}    |
| |\                 +----------------+-----------------------------+-----------------------------+
| | +Expand(All)     |              2 | anon[53], anon[71] -- other | (other)-[:FRIENDS_WITH]->() |
| | |                +----------------+-----------------------------+-----------------------------+
| | +Argument        |             14 | other                       |                             |
| |                  +----------------+-----------------------------+-----------------------------+
| +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

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 

+------------------------+----------------+-----------------------------+-----------------------------+
| Operator               | Estimated Rows | Variables                   | Other                       |
+------------------------+----------------+-----------------------------+-----------------------------+
| +ProduceResults        |              4 | other.name                  | other.name                  |
| |                      +----------------+-----------------------------+-----------------------------+
| +Projection            |              4 | other.name -- other         | other.name                  |
| |                      +----------------+-----------------------------+-----------------------------+
| +SelectOrAntiSemiApply |              4 | other                       | other.age > {  AUTOINT0}    |
| |\                     +----------------+-----------------------------+-----------------------------+
| | +Expand(All)         |              2 | anon[57], anon[75] -- other | (other)-[:FRIENDS_WITH]->() |
| | |                    +----------------+-----------------------------+-----------------------------+
| | +Argument            |             14 | other                       |                             |
| |                      +----------------+-----------------------------+-----------------------------+
| +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

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 

+-----------------------+----------------+-----------+---------------+
| Operator              | Estimated Rows | Variables | Other         |
+-----------------------+----------------+-----------+---------------+
| +ProduceResults       |              1 |           |               |
| |                     +----------------+-----------+---------------+
| +EmptyResult          |                |           |               |
| |                     +----------------+-----------+---------------+
| +AntiConditionalApply |              1 | p         |               |
| |\                    +----------------+-----------+---------------+
| | +MergeCreateNode    |              1 | p         |               |
| |                     +----------------+-----------+---------------+
| +ConditionalApply     |              1 | p         |               |
| |\                    +----------------+-----------+---------------+
| | +SetNodeProperty    |              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

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 

+-----------------------+----------------+-----------+---------------+
| Operator              | Estimated Rows | Variables | Other         |
+-----------------------+----------------+-----------+---------------+
| +ProduceResults       |              1 |           |               |
| |                     +----------------+-----------+---------------+
| +EmptyResult          |                |           |               |
| |                     +----------------+-----------+---------------+
| +AntiConditionalApply |              1 | p         |               |
| |\                    +----------------+-----------+---------------+
| | +SetNodeProperty    |              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

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. Due to the existence of two uniqueness constraints on :Team(name) and :Team(id), any node that would be found by the `UniqueIndexSeek`s must be the very same node, or the constraints would be violated.

Query plan 

+---------------------------------+----------------+-----------+-------------+
| Operator                        | Estimated Rows | Variables | Other       |
+---------------------------------+----------------+-----------+-------------+
| +ProduceResults                 |              1 |           |             |
| |                               +----------------+-----------+-------------+
| +EmptyResult                    |                |           |             |
| |                               +----------------+-----------+-------------+
| +AntiConditionalApply           |              1 | t         |             |
| |\                              +----------------+-----------+-------------+
| | +MergeCreateNode              |              1 | t         |             |
| |                               +----------------+-----------+-------------+
| +Optional                       |              1 | t         |             |
| |                               +----------------+-----------+-------------+
| +AssertSameNode                 |              0 | t         |             |
| |\                              +----------------+-----------+-------------+
| | +NodeUniqueIndexSeek(Locking) |              1 | t         | :Team(id)   |
| |                               +----------------+-----------+-------------+
| +NodeUniqueIndexSeek(Locking)   |              1 | t         | :Team(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 (t:Team {name: 'Engineering', id: 42})

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 

+------------------+----------------+-------------------------------------------------+---------------------------+
| Operator         | Estimated Rows | Variables                                       | Other                     |
+------------------+----------------+-------------------------------------------------+---------------------------+
| +ProduceResults  |             10 | loc.name                                        | loc.name                  |
| |                +----------------+-------------------------------------------------+---------------------------+
| +Projection      |             10 | loc.name -- anon[37], anon[56], andy, loc, matt | loc.name                  |
| |                +----------------+-------------------------------------------------+---------------------------+
| +Filter          |             10 | anon[37], anon[56], andy, loc, matt             | NOT(anon[37] == anon[56]) |
| |                +----------------+-------------------------------------------------+---------------------------+
| +NodeHashJoin    |             10 | anon[37], andy -- anon[56], loc, matt           | loc                       |
| |\               +----------------+-------------------------------------------------+---------------------------+
| | +Expand(All)   |             19 | anon[56], loc -- matt                           | (matt)-[:WORKS_IN]->(loc) |
| | |              +----------------+-------------------------------------------------+---------------------------+
| | +NodeIndexSeek |              1 | matt                                            | :Person(name)             |
| |                +----------------+-------------------------------------------------+---------------------------+
| +Expand(All)     |             19 | anon[37], 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

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 

+-------------------+----------------+-------------------------------------------------------+----------------------------+
| Operator          | Estimated Rows | Variables                                             | Other                      |
+-------------------+----------------+-------------------------------------------------------+----------------------------+
| +ProduceResults   |              0 | other.name                                            | other.name                 |
| |                 +----------------+-------------------------------------------------------+----------------------------+
| +Projection       |              0 | other.name -- anon[18], anon[35], anon[37], me, other | other.name                 |
| |                 +----------------+-------------------------------------------------------+----------------------------+
| +TriadicSelection |              0 | anon[18], anon[35], me -- anon[37], other             | me, anon[35], other        |
| |\                +----------------+-------------------------------------------------------+----------------------------+
| | +Filter         |              0 | anon[37], other                                       | NOT(anon[18] == anon[37])  |
| | |               +----------------+-------------------------------------------------------+----------------------------+
| | +Expand(All)    |              0 | anon[37], other                                       | ()-[:FRIENDS_WITH]-(other) |
| | |               +----------------+-------------------------------------------------------+----------------------------+
| | +Argument       |              4 |                                                       |                            |
| |                 +----------------+-------------------------------------------------------+----------------------------+
| +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