These operators take rows produced by another operator and transform them to a different set of rows
Eager
For isolation purposes this operator makes sure that operations that affect subsequent operations are executed fully for the whole dataset before continuing execution. Otherwise it could trigger endless loops, matching data again, that was just created. The Eager operator can cause high memory usage when importing data or migrating graph structures. In such cases split up your operations into simpler steps e.g. you can import nodes and relationships separately. Alternatively return the records to be updated and run an update statement afterwards.
Query
MATCH (a)-[r]-(b) DELETE r,a,b MERGE ()
Query Plan
+-------------------------+----------------+------+---------+---------------------+--------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-------------------------+----------------+------+---------+---------------------+--------------+ | +ProduceResults | 1 | 0 | 0 | | | | | +----------------+------+---------+---------------------+--------------+ | +EmptyResult | | 0 | 0 | | | | | +----------------+------+---------+---------------------+--------------+ | +Apply | 1 | 504 | 0 | a, b, r -- anon[38] | | | |\ +----------------+------+---------+---------------------+--------------+ | | +AntiConditionalApply | 1 | 504 | 0 | anon[38] | | | | |\ +----------------+------+---------+---------------------+--------------+ | | | +MergeCreateNode | 1 | 0 | 0 | anon[38] | | | | | +----------------+------+---------+---------------------+--------------+ | | +Optional | 35 | 504 | 0 | anon[38] | | | | | +----------------+------+---------+---------------------+--------------+ | | +AllNodesScan | 35 | 504 | 540 | anon[38] | | | | +----------------+------+---------+---------------------+--------------+ | +Eager | | 36 | 0 | a, b, r | | | | +----------------+------+---------+---------------------+--------------+ | +Delete(3) | 36 | 36 | 39 | a, b, r | | | | +----------------+------+---------+---------------------+--------------+ | +Eager | | 36 | 0 | a, b, r | | | | +----------------+------+---------+---------------------+--------------+ | +Expand(All) | 36 | 36 | 71 | a, r -- b | (b)-[r:]-(a) | | | +----------------+------+---------+---------------------+--------------+ | +AllNodesScan | 35 | 35 | 36 | b | | +-------------------------+----------------+------+---------+---------------------+--------------+ Total database accesses: 686
Distinct
Removes duplicate rows from the incoming stream of rows.
Query
MATCH (l:Location)<-[:WORKS_IN]-(p:Person) RETURN DISTINCT l
Query Plan
+------------------+----------------+------+---------+------------------+----------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +------------------+----------------+------+---------+------------------+----------------------+ | +ProduceResults | 14 | 6 | 0 | l | l | | | +----------------+------+---------+------------------+----------------------+ | +Distinct | 14 | 6 | 0 | l | l | | | +----------------+------+---------+------------------+----------------------+ | +Filter | 15 | 15 | 15 | anon[19], l, p | p:Person | | | +----------------+------+---------+------------------+----------------------+ | +Expand(All) | 15 | 15 | 25 | anon[19], p -- l | (l)<-[:WORKS_IN]-(p) | | | +----------------+------+---------+------------------+----------------------+ | +NodeByLabelScan | 10 | 10 | 11 | l | :Location | +------------------+----------------+------+---------+------------------+----------------------+ Total database accesses: 51
Eager Aggregation
Eagerly loads underlying results and stores it in a hash-map, using the grouping keys as the keys for the map.
Query
MATCH (l:Location)<-[:WORKS_IN]-(p:Person) RETURN l.name AS location, COLLECT(p.name) AS people
Query Plan
+-------------------+----------------+------+---------+----------------------------+----------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-------------------+----------------+------+---------+----------------------------+----------------------+ | +ProduceResults | 4 | 6 | 0 | location, people | location, people | | | +----------------+------+---------+----------------------------+----------------------+ | +EagerAggregation | 4 | 6 | 15 | people -- location | location | | | +----------------+------+---------+----------------------------+----------------------+ | +Projection | 15 | 15 | 15 | location -- anon[19], l, p | l.name; p | | | +----------------+------+---------+----------------------------+----------------------+ | +Filter | 15 | 15 | 15 | anon[19], l, p | p:Person | | | +----------------+------+---------+----------------------------+----------------------+ | +Expand(All) | 15 | 15 | 25 | anon[19], p -- l | (l)<-[:WORKS_IN]-(p) | | | +----------------+------+---------+----------------------------+----------------------+ | +NodeByLabelScan | 10 | 10 | 11 | l | :Location | +-------------------+----------------+------+---------+----------------------------+----------------------+ Total database accesses: 81
Node Count From Count Store
Use the count store to answer questions about node counts. This is much faster than eager aggregation which achieves the same result by actually counting. However the count store only saves a limited range of combinations, so eager aggregation will still be used for more complex queries. For example, we can get counts for all nodes, and nodes with a label, but not nodes with more than one label.
Query
MATCH (p:Person) RETURN count(p) AS people
Query Plan
+--------------------------+----------------+------+---------+-----------+------------------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +--------------------------+----------------+------+---------+-----------+------------------------------+ | +ProduceResults | 4 | 1 | 0 | people | people | | | +----------------+------+---------+-----------+------------------------------+ | +NodeCountFromCountStore | 4 | 1 | 0 | people | count( (:Person) ) AS people | +--------------------------+----------------+------+---------+-----------+------------------------------+ Total database accesses: 0
Relationship Count From Count Store
Use the count store to answer questions about relationship counts. This is much faster than eager aggregation which achieves the same result by actually counting. However the count store only saves a limited range of combinations, so eager aggregation will still be used for more complex queries. For example, we can get counts for all relationships, relationships with a type, relationships with a label on one end, but not relationships with labels on both end nodes.
Query
MATCH (p:Person)-[r:WORKS_IN]->() RETURN count(r) AS jobs
Query Plan
+----------------------------------+----------------+------+---------+-----------+--------------------------------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +----------------------------------+----------------+------+---------+-----------+--------------------------------------------+ | +ProduceResults | 4 | 1 | 0 | jobs | jobs | | | +----------------+------+---------+-----------+--------------------------------------------+ | +RelationshipCountFromCountStore | 4 | 1 | 1 | jobs | count( (:Person)-[:WORKS_IN]->() ) AS jobs | +----------------------------------+----------------+------+---------+-----------+--------------------------------------------+ Total database accesses: 1
Filter
Filters each row coming from the child operator, only passing through rows that evaluate the predicates to TRUE
.
Query
MATCH (p:Person) WHERE p.name =~ "^a.*" RETURN p
Query Plan
+------------------+----------------+------+---------+-----------+-----------------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +------------------+----------------+------+---------+-----------+-----------------------------+ | +ProduceResults | 14 | 0 | 0 | p | p | | | +----------------+------+---------+-----------+-----------------------------+ | +Filter | 14 | 0 | 14 | p | p.name ~= /{ AUTOSTRING0}/ | | | +----------------+------+---------+-----------+-----------------------------+ | +NodeByLabelScan | 14 | 14 | 15 | p | :Person | +------------------+----------------+------+---------+-----------+-----------------------------+ Total database accesses: 29
Limit
Returns the first n rows from the incoming input.
Query
MATCH (p:Person) RETURN p LIMIT 3
Query Plan
+------------------+----------------+------+---------+-----------+------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +------------------+----------------+------+---------+-----------+------------+ | +ProduceResults | 3 | 3 | 0 | p | p | | | +----------------+------+---------+-----------+------------+ | +Limit | 3 | 3 | 0 | p | Literal(3) | | | +----------------+------+---------+-----------+------------+ | +NodeByLabelScan | 14 | 3 | 4 | p | :Person | +------------------+----------------+------+---------+-----------+------------+ Total database accesses: 4
Projection
For each row from its input, projection evaluates a set of expressions and produces a row with the results of the expressions.
Query
RETURN "hello" AS greeting
Query Plan
+-----------------+----------------+------+---------+-----------+-----------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------+----------------+------+---------+-----------+-----------------+ | +ProduceResults | 1 | 1 | 0 | greeting | greeting | | | +----------------+------+---------+-----------+-----------------+ | +Projection | 1 | 1 | 0 | greeting | { AUTOSTRING0} | +-----------------+----------------+------+---------+-----------+-----------------+ Total database accesses: 0
Skip
Skips n rows from the incoming rows
Query
MATCH (p:Person) RETURN p ORDER BY p.id SKIP 1
Query Plan
+------------------+----------------+------+---------+----------------------------+-----------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +------------------+----------------+------+---------+----------------------------+-----------------------+ | +ProduceResults | 14 | 13 | 0 | p | p | | | +----------------+------+---------+----------------------------+-----------------------+ | +Projection | 14 | 13 | 0 | p -- anon[35], anon[59], p | anon[35] | | | +----------------+------+---------+----------------------------+-----------------------+ | +Skip | 14 | 13 | 0 | anon[35], anon[59], p | { AUTOINT0} | | | +----------------+------+---------+----------------------------+-----------------------+ | +Sort | 14 | 14 | 0 | anon[35], anon[59], p | anon[59] | | | +----------------+------+---------+----------------------------+-----------------------+ | +Projection | 14 | 14 | 28 | anon[59] -- anon[35], p | anon[35]; anon[35].id | | | +----------------+------+---------+----------------------------+-----------------------+ | +Projection | 14 | 14 | 0 | anon[35] -- p | p | | | +----------------+------+---------+----------------------------+-----------------------+ | +NodeByLabelScan | 14 | 14 | 15 | p | :Person | +------------------+----------------+------+---------+----------------------------+-----------------------+ Total database accesses: 43
Sort
Sorts rows by a provided key.
Query
MATCH (p:Person) RETURN p ORDER BY p.name
Query Plan
+------------------+----------------+------+---------+----------------------------+-------------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +------------------+----------------+------+---------+----------------------------+-------------------------+ | +ProduceResults | 14 | 14 | 0 | p | p | | | +----------------+------+---------+----------------------------+-------------------------+ | +Projection | 14 | 14 | 0 | p -- anon[24], anon[37], p | anon[24] | | | +----------------+------+---------+----------------------------+-------------------------+ | +Sort | 14 | 14 | 0 | anon[24], anon[37], p | anon[37] | | | +----------------+------+---------+----------------------------+-------------------------+ | +Projection | 14 | 14 | 14 | anon[37] -- anon[24], p | anon[24]; anon[24].name | | | +----------------+------+---------+----------------------------+-------------------------+ | +Projection | 14 | 14 | 0 | anon[24] -- p | p | | | +----------------+------+---------+----------------------------+-------------------------+ | +NodeByLabelScan | 14 | 14 | 15 | p | :Person | +------------------+----------------+------+---------+----------------------------+-------------------------+ Total database accesses: 29
Top
Returns the first n rows sorted by a provided key. The physical operator is called Top
. Instead of sorting the whole input, only the top X rows are kept.
Query
MATCH (p:Person) RETURN p ORDER BY p.name LIMIT 2
Query Plan
+------------------+----------------+------+---------+----------------------------+-------------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +------------------+----------------+------+---------+----------------------------+-------------------------+ | +ProduceResults | 2 | 2 | 0 | p | p | | | +----------------+------+---------+----------------------------+-------------------------+ | +Projection | 2 | 2 | 0 | p -- anon[24], anon[37], p | anon[24] | | | +----------------+------+---------+----------------------------+-------------------------+ | +Top | 2 | 2 | 0 | anon[24], anon[37], p | Literal(2); anon[37] | | | +----------------+------+---------+----------------------------+-------------------------+ | +Projection | 14 | 14 | 14 | anon[37] -- anon[24], p | anon[24]; anon[24].name | | | +----------------+------+---------+----------------------------+-------------------------+ | +Projection | 14 | 14 | 0 | anon[24] -- p | p | | | +----------------+------+---------+----------------------------+-------------------------+ | +NodeByLabelScan | 14 | 14 | 15 | p | :Person | +------------------+----------------+------+---------+----------------------------+-------------------------+ Total database accesses: 29
Union
Union concatenates the results from the right plan after the results of the left plan.
Query
MATCH (p:Location) RETURN p.name UNION ALL MATCH (p:Country) RETURN p.name
Query Plan
+--------------------+----------------+------+---------+-------------+-----------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +--------------------+----------------+------+---------+-------------+-----------+ | +ProduceResults | 10 | 11 | 0 | p.name | p.name | | | +----------------+------+---------+-------------+-----------+ | +Union | 10 | 11 | 0 | p.name | | | |\ +----------------+------+---------+-------------+-----------+ | | +Projection | 1 | 1 | 1 | p.name -- p | p.name | | | | +----------------+------+---------+-------------+-----------+ | | +NodeByLabelScan | 1 | 1 | 2 | p | :Country | | | +----------------+------+---------+-------------+-----------+ | +Projection | 10 | 10 | 10 | p.name -- p | p.name | | | +----------------+------+---------+-------------+-----------+ | +NodeByLabelScan | 10 | 10 | 11 | p | :Location | +--------------------+----------------+------+---------+-------------+-----------+ Total database accesses: 24
Unwind
Takes a list of values and returns one row per item in the list.
Query
UNWIND range(1,5) AS value RETURN value;
Query Plan
+-----------------+----------------+------+---------+-----------+-------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------+----------------+------+---------+-----------+-------+ | +ProduceResults | 10 | 5 | 0 | value | value | | | +----------------+------+---------+-----------+-------+ | +Unwind | 10 | 5 | 0 | value | | | | +----------------+------+---------+-----------+-------+ | +EmptyRow | 1 | 1 | 0 | | | +-----------------+----------------+------+---------+-----------+-------+ Total database accesses: 0
Call Procedure
Return all labels sorted by name
Query
CALL db.labels()YIELD label RETURN * ORDER BY label
Query Plan
+-----------------+----------------+------+---------+-----------+----------------------------------+ | Operator | Estimated Rows | Rows | DB Hits | Variables | Other | +-----------------+----------------+------+---------+-----------+----------------------------------+ | +ProduceResults | 10000 | 4 | 0 | label | label | | | +----------------+------+---------+-----------+----------------------------------+ | +Sort | 10000 | 4 | 0 | label | label | | | +----------------+------+---------+-----------+----------------------------------+ | +ProcedureCall | 10000 | 4 | 1 | label | db.labels() :: (label :: String) | | | +----------------+------+---------+-----------+----------------------------------+ | +EmptyRow | 1 | 1 | 0 | | | +-----------------+----------------+------+---------+-----------+----------------------------------+ Total database accesses: 1