Operators
This page contains an overview of the available Cypher® operators.
Operators at a glance
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Aggregation operators
The aggregation operators comprise:
-
remove duplicates values:
DISTINCT
Using the DISTINCT
operator
Retrieve the unique eye colors from Person
nodes.
CREATE
(a:Person {name: 'Anne', eyeColor: 'blue'}),
(b:Person {name: 'Bill', eyeColor: 'brown'}),
(c:Person {name: 'Carol', eyeColor: 'blue'})
WITH [a, b, c] AS ps
UNWIND ps AS p
RETURN DISTINCT p.eyeColor
Even though both 'Anne' and 'Carol' have blue eyes, 'blue' is only returned once.
p.eyeColor |
---|
|
|
Rows: 2 |
DISTINCT
is commonly used in conjunction with aggregating functions.
Property operators
The property operators pertain to a node or a relationship, and comprise:
-
statically access the property of a node or relationship using the dot operator:
.
-
dynamically access the property of a node or relationship using the subscript operator:
[]
-
property replacement
=
for replacing all properties of a node or relationship -
property mutation operator
+=
for setting specific properties of a node or relationship
Statically accessing a property of a node or relationship using the .
operator
CREATE
(a:Person {name: 'Jane', livesIn: 'London'}),
(b:Person {name: 'Tom', livesIn: 'Copenhagen'})
WITH a, b
MATCH (p:Person)
RETURN p.name
p.name |
---|
|
|
Rows: 2 |
Filtering on a dynamically-computed property key using the []
operator
CREATE
(a:Restaurant {name: 'Hungry Jo', rating_hygiene: 10, rating_food: 7}),
(b:Restaurant {name: 'Buttercup Tea Rooms', rating_hygiene: 5, rating_food: 6}),
(c1:Category {name: 'hygiene'}),
(c2:Category {name: 'food'})
WITH a, b, c1, c2
MATCH (restaurant:Restaurant), (category:Category)
WHERE restaurant["rating_" + category.name] > 6
RETURN DISTINCT restaurant.name
restaurant.name |
---|
|
Rows: 1 |
See Basic usage for more details on dynamic property access.
The behavior of the |
Replacing all properties of a node or relationship using the =
operator
CREATE (a:Person {name: 'Sofia', age: 20})
WITH a
MATCH (p:Person {name: 'Sofia'})
SET p = {name: 'Ellen', livesIn: 'London'}
RETURN p.name, p.age, p.livesIn
All the existing properties on the node are replaced by those provided in the map; i.e. the name
property is updated from Sofia
to Ellen
, the age
property is deleted, and the livesIn
property is added.
p.name | p.age | p.livesIn |
---|---|---|
|
|
|
Rows: 1 |
See Replace all properties using a map and =
for more details on using the property replacement operator =
.
Mutating specific properties of a node or relationship using the +=
operator
CREATE (a:Person {name: 'Sofia', age: 20})
WITH a
MATCH (p:Person {name: 'Sofia'})
SET p += {name: 'Ellen', livesIn: 'London'}
RETURN p.name, p.age, p.livesIn
The properties on the node are updated as follows by those provided in the map: the name
property is updated from Sofia
to Ellen
, the age
property is left untouched, and the livesIn
property is added.
p.name | p.age | p.livesIn |
---|---|---|
|
|
|
Rows: 1 |
See Mutate specific properties using a map and +=
for more details on using the property mutation operator +=
.
Mathematical operators
Comparison operators
The comparison operators comprise:
-
equality:
=
-
inequality:
<>
-
less than:
<
-
greater than:
>
-
less than or equal to:
<=
-
greater than or equal to:
>=
-
IS NULL
-
IS NOT NULL
STRING
-specific comparison operators comprise:
-
STARTS WITH
: perform case-sensitive prefix searching onSTRING
values. -
ENDS WITH
: perform case-sensitive suffix searching onSTRING
values. -
CONTAINS
: perform case-sensitive inclusion searching inSTRING
values. -
=~
: regular expression for matching a pattern.
Comparing two numbers
WITH 4 AS one, 3 AS two
RETURN one > two AS result
result |
---|
|
Rows: 1 |
See Equality and comparison of values for more details on the behavior of comparison operators, and Using ranges for more examples showing how these may be used.
Using STARTS WITH
to filter names
WITH ['John', 'Mark', 'Jonathan', 'Bill'] AS somenames
UNWIND somenames AS names
WITH names AS candidate
WHERE candidate STARTS WITH 'Jo'
RETURN candidate
candidate |
---|
|
|
Rows: 2 |
STRING
matching contains more information regarding the STRING
-specific comparison operators as well as additional examples illustrating the usage thereof.
Equality and comparison of values
Equality
Cypher supports comparing values (see Property, structural, and constructed values) by equality using the =
and <>
operators.
Values of the same type are only equal if they are the same identical value (e.g. 3 = 3
and "x" <> "xy"
).
Maps are only equal if they map exactly the same keys to equal values and lists are only equal if they contain the same sequence of equal values (e.g. [3, 4] = [1+2, 8/2]
).
Values of different types are considered as equal according to the following rules:
-
Paths are treated as lists of alternating nodes and relationships and are equal to all lists that contain that very same sequence of nodes and relationships.
-
Testing any value against
null
with both the=
and the<>
operators always evaluates tonull
. This includesnull = null
andnull <> null
. The only way to reliably test if a valuev
isnull
is by using the specialv IS NULL
, orv IS NOT NULL
, equality operators.v IS NOT NULL
is equivalent toNOT(v IS NULL)
.
All other combinations of types of values cannot be compared with each other. Especially, nodes, relationships, and literal maps are incomparable with each other.
It is an error to compare values that cannot be compared.
Ordering and comparison of values
The comparison operators <=
, <
(for ascending) and >=
, >
(for descending) are used to compare values for ordering.
The following points give some details on how the comparison is performed.
-
Numerical values are compared for ordering using numerical order (e.g.
3 < 4
is true). -
All comparability tests (
<
,<=
,>
,>=
) withjava.lang.Double.NaN
evaluate as false. For example,1 > b
and1 < b
are both false when b is NaN. -
String values are compared for ordering using lexicographic order (e.g.
"x" < "xy"
). -
Boolean values are compared for ordering such that
false < true
. -
Spatial values cannot be compared using the operators
<
,<=
,>
, or>=
. To compare spatial values within a specific range, use either thepoint.withinBBox()
or thepoint()
function. -
Ordering of spatial values:
-
ORDER BY
requires all values to be orderable. -
Points are ordered after arrays and before temporal types.
-
Points of different CRS are ordered by the CRS code (the value of SRID field). For the currently supported set of Coordinate Reference Systems this means the order: 4326, 4979, 7302, 9157
-
Points of the same CRS are ordered by each coordinate value in turn,
x
first, theny
and finallyz
. -
Note that this order is different to the order returned by the spatial index, which will be the order of the space filling curve.
-
-
Comparison of temporal values:
-
Temporal instant values are comparable within the same type. An instant is considered less than another instant if it occurs before that instant in time, and it is considered greater than if it occurs after.
-
Instant values that occur at the same point in time — but that have a different time zone — are not considered equal, and must therefore be ordered in some predictable way. Cypher prescribes that, after the primary order of point in time, instant values be ordered by effective time zone offset, from west (negative offset from UTC) to east (positive offset from UTC). This has the effect that times that represent the same point in time will be ordered with the time with the earliest local time first. If two instant values represent the same point in time, and have the same time zone offset, but a different named time zone (this is possible for DateTime only, since Time only has an offset), these values are not considered equal, and ordered by the time zone identifier, alphabetically, as its third ordering component. If the type, point in time, offset, and time zone name are all equal, then the values are equal, and any difference in order is impossible to observe.
-
Duration values cannot be compared, since the length of a day, month or year is not known without knowing which day, month or year it is. Since Duration values are not comparable, the result of applying a comparison operator between two Duration values is
null
.
-
-
Ordering of temporal values:
-
ORDER BY
requires all values to be orderable. -
Temporal instances are ordered after spatial instances and before strings.
-
Comparable values should be ordered in the same order as implied by their comparison order.
-
Temporal instant values are first ordered by type, and then by comparison order within the type.
-
Since no complete comparison order can be defined for Duration values, we define an order for
ORDER BY
specifically for Duration:-
Duration values are ordered by normalising all components as if all years were
365.2425
days long (PT8765H49M12S
), all months were30.436875
(1/12
year) days long (PT730H29M06S
), and all days were24
hours long [1].
-
-
-
Comparing for ordering when one argument is
null
(e.g.null < 3
isnull
). -
Ordering of values with different types:
-
The ordering is, in ascending order, defined according to the following list:
-
The value
null
is ordered after all other values.
-
-
Ordering of constructed type values:
-
For the constructed types (e.g. maps and lists), elements of the containers are compared pairwise for ordering and thus determine the ordering of two container types. For example,
[1, 'foo', 3]
is ordered before[1, 2, 'bar']
since'foo'
is ordered before2
.
-
Chaining comparison operations
Comparisons can be chained arbitrarily, e.g., x < y <= z
is equivalent to x < y AND y <= z
.
Formally, if a, b, c, ..., y, z
are expressions and op1, op2, ..., opN
are comparison operators, then a op1 b op2 c ... y opN z
is equivalent to a op1 b and b op2 c and ... y opN z
.
Note that a op1 b op2 c
does not imply any kind of comparison between a
and c
, so that, e.g., x < y > z
is perfectly legal (although perhaps not elegant).
The example:
MATCH (n) WHERE 21 < n.age <= 30 RETURN n
is equivalent to
MATCH (n) WHERE 21 < n.age AND n.age <= 30 RETURN n
Thus, it matches all nodes where the age is between 21 and 30.
This syntax extends to all equality =
and inequality <>
comparisons, as well as to chains longer than three.
Chains of This means that |
For example:
a < b = c <= d <> e
Is equivalent to:
a < b AND b = c AND c <= d AND d <> e
Using a regular expression with =~
to filter words
WITH ['mouse', 'chair', 'door', 'house'] AS wordlist
UNWIND wordlist AS word
WITH word
WHERE word =~ '.*ous.*'
RETURN word
word |
---|
|
|
Rows: 2 |
Further information and examples regarding the use of regular expressions in filtering can be found in Regular expressions.
Boolean operators
The boolean operators — also known as logical operators — comprise:
-
conjunction:
AND
-
disjunction:
OR
, -
exclusive disjunction:
XOR
-
negation:
NOT
Here is the truth table for AND
, OR
, XOR
and NOT
.
a | b | a AND b |
a OR b |
a XOR b |
NOT a |
---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String operators
The string operators comprise:
-
concatenating
STRING
values:+
and||
-
checking if a
STRING
is normalized:IS NORMALIZED
Concatenating two STRING
values with +
Using +
to concatenate strings is functionally equivalent to using ||
.
However, the +
string concatenation operator is not GQL conformant.
RETURN 'neo' + '4j' AS result
result |
---|
|
Rows: 1 |
Concatenating two STRING
values with ||
RETURN 'neo' || '4j' AS result
result |
---|
|
Rows: 1 |
Checking if a STRING
IS NORMALIZED
The IS NORMALIZED
operator is used to check whether the given STRING
is in the NFC
Unicode normalization form:
Unicode normalization is a process that transforms different representations of the same string into a standardized form. For more information, see the documentation for Unicode normalization forms. |
RETURN "the \u212B char" IS NORMALIZED AS normalized
normalized |
---|
|
Because the given STRING
contains a non-normalized Unicode character (\u212B
), false
is returned.
To normalize a STRING
, use the normalize() function.
Note that the IS NORMALIZED
operator returns null
when used on a non-STRING
value.
For example, RETURN 1 IS NORMALIZED
returns null
.
Checking if a STRING
IS NOT NORMALIZED
The IS NOT NORMALIZED
operator is used to check whether the given STRING
is not in the NFC
Unicode normalization form:
RETURN "the \u212B char" IS NOT NORMALIZED AS notNormalized
notNormalized |
---|
|
Because the given STRING
contains a non-normalized Unicode character (\u212B
), and is not normalized, true
is returned.
To normalize a STRING
, use the normalize() function.
Note that the IS NOT NORMALIZED
operator returns null
when used on a non-STRING
value.
For example, RETURN 1 IS NOT NORMALIZED
returns null
.
Using IS NORMALIZED
with a specified normalization type
It is possible to define which Unicode normalization type is used (the default is NFC
).
The available normalization types are:
-
NFC
-
NFD
-
NFKC
-
NFKD
WITH "the \u00E4 char" as myString
RETURN myString IS NFC NORMALIZED AS nfcNormalized,
myString IS NFD NORMALIZED AS nfdNormalized
The given STRING
contains the Unicode character: \u00E4
, which is considered normalized in NFC
form, but not in NFD
form.
nfcNormalized | nfdNormalized |
---|---|
|
|
|
It is also possible to specify the normalization form when using the negated normalization operator.
For example, RETURN "string" IS NOT NFD NORMALIZED
.
Temporal operators
Temporal operators comprise:
-
adding a
DURATION
to either a temporal instant or anotherDURATION
:+
-
subtracting a
DURATION
from either a temporal instant or anotherDURATION
:-
-
multiplying a
DURATION
with a number:*
-
dividing a
DURATION
by a number:/
The following table shows — for each combination of operation and operand type — the type of the value returned from the application of each temporal operator:
Operator | Left-hand operand | Right-hand operand | Type of result |
---|---|---|---|
Temporal instant |
|
The type of the temporal instant |
|
|
Temporal instant |
The type of the temporal instant |
|
Temporal instant |
|
The type of the temporal instant |
|
|
|
|
|
|
|
|
|
|
|
||
|
|
||
|
|
Adding and subtracting a DURATION
to or from a temporal instant
WITH
localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14}) AS aDateTime,
duration({years: 12, nanoseconds: 2}) AS aDuration
RETURN aDateTime + aDuration, aDateTime - aDuration
aDateTime + aDuration | aDateTime - aDuration |
---|---|
|
|
Rows: 1 |
Components of a DURATION
that do not apply to the temporal instant are ignored.
For example, when adding a DURATION
to a DATE
, the hours, minutes, seconds and nanoseconds of the DURATION
are ignored (ZONED TIME
and LOCAL TIME
behaves in an analogous manner):
WITH
date({year:1984, month:10, day:11}) AS aDate,
duration({years: 12, nanoseconds: 2}) AS aDuration
RETURN aDate + aDuration, aDate - aDuration
aDate + aDuration | aDate - aDuration |
---|---|
|
|
Rows: 1 |
Adding two durations to a temporal instant is not an associative operation. This is because non-existing dates are truncated to the nearest existing date:
RETURN
(date("2011-01-31") + duration("P1M")) + duration("P12M") AS date1,
date("2011-01-31") + (duration("P1M") + duration("P12M")) AS date2
date1 | date2 |
---|---|
|
|
Rows: 1 |
Adding and subtracting a DURATION
to or from another DURATION
WITH
duration({years: 12, months: 5, days: 14, hours: 16, minutes: 12, seconds: 70, nanoseconds: 1}) as duration1,
duration({months:1, days: -14, hours: 16, minutes: -12, seconds: 70}) AS duration2
RETURN duration1, duration2, duration1 + duration2, duration1 - duration2
duration1 | duration2 | duration1 + duration2 | duration1 - duration2 |
---|---|---|---|
|
|
|
|
Rows: 1 |
Multiplying and dividing a DURATION
with or by a number
These operations are interpreted simply as component-wise operations with overflow to smaller units based on an average length of units in the case of division (and multiplication with fractions).
WITH duration({days: 14, minutes: 12, seconds: 70, nanoseconds: 1}) AS aDuration
RETURN aDuration, aDuration * 2, aDuration / 3
aDuration | aDuration * 2 | aDuration / 3 |
---|---|---|
|
|
|
Rows: 1 |
Map operators
The map operators comprise:
-
statically access the value of a map by key using the dot operator:
.
-
dynamically access the value of a map by key using the subscript operator:
[]
The behavior of the |
Statically accessing the value of a nested map by key using the .
operator
WITH {person: {name: 'Anne', age: 25}} AS p
RETURN p.person.name
p.person.name |
---|
|
Rows: 1 |
Dynamically accessing the value of a map by key using the []
operator and a parameter
A parameter may be used to specify the key of the value to access:
{
"myKey" : "name"
}
WITH {name: 'Anne', age: 25} AS a
RETURN a[$myKey] AS result
result |
---|
|
Rows: 1 |
More information can be found in the Maps chapter.
List operators
The list operators comprise:
-
concatenating lists
l1
andl2
:[l1] + [l2]
and[l1] || [l2]
-
checking if an element
e
exists in a listl
:e IN [l]
-
dynamically accessing an element(s) in a list using the subscript operator:
[]
The behavior of the |
Concatenating two lists using +
RETURN [1,2,3,4,5] + [6,7] AS myList
myList |
---|
|
Rows: 1 |
Concatenating two lists using ||
RETURN [1,2,3,4,5] || [6,7] AS myList
myList |
---|
|
Rows: 1 |
Using IN
to check if a number is in a list
WITH [2, 3, 4, 5] AS numberlist
UNWIND numberlist AS number
WITH number
WHERE number IN [2, 3, 8]
RETURN number
number |
---|
|
|
Rows: 2 |
Using IN
for more complex list membership operations
The general rule is that the IN
operator will evaluate to true
if the list given as the right-hand operand contains an element which has the same type and contents (or value) as the left-hand operand.
Lists are only comparable to other lists, and elements of a list innerList
are compared pairwise in ascending order from the first element in innerList
to the last element in innerList
.
The following query checks whether or not the list [2, 1]
is an element of the list [1, [2, 1], 3]
:
RETURN [2, 1] IN [1, [2, 1], 3] AS inList
The query evaluates to true
as the right-hand list contains, as an element, the list [1, 2]
which is of the same type (a list) and contains the same contents (the numbers 2
and 1
in the given order) as the left-hand operand.
If the left-hand operator had been [1, 2]
instead of [2, 1]
, the query would have returned false
.
inList |
---|
|
Rows: 1 |
At first glance, the contents of the left-hand operand and the right-hand operand appear to be the same in the following query:
RETURN [1, 2] IN [1, 2] AS inList
However, IN
evaluates to false
as the right-hand operand does not contain an element that is of the same type — i.e. a list — as the left-hand-operand.
inList |
---|
|
Rows: 1 |
The following query can be used to ascertain whether or not a list — obtained from, say, the labels() function — contains at least one element that is also present in another list:
MATCH (n)
WHERE size([label IN labels(n) WHERE label IN ['Person', 'Employee'] | 1]) > 0
RETURN count(n)
As long as labels(n)
returns either Person
or Employee
(or both), the query will return a value greater than zero.
Accessing elements in a list using the []
operator
WITH ['Anne', 'John', 'Bill', 'Diane', 'Eve'] AS names
RETURN names[1..3] AS result
The square brackets will extract the elements from the start index 1
, and up to (but excluding) the end index 3
.
result |
---|
|
Rows: 1 |
Dynamically accessing an element in a list using the []
operator and a parameter
A parameter may be used to specify the index of the element to access:
{
"myIndex" : 1
}
WITH ['Anne', 'John', 'Bill', 'Diane', 'Eve'] AS names
RETURN names[$myIndex] AS result
result |
---|
|
Rows: 1 |
Using IN
with []
on a nested list
IN
can be used in conjunction with []
to test whether an element exists in a nested list:
WITH [[1, 2, 3]] AS l
RETURN 3 IN l[0] AS result
result |
---|
|
Rows: 1 |
More details on lists can be found in Lists in general.
365.2425
days per year comes from the frequency of leap years. A leap year occurs on a year with an ordinal number divisible by 4
, that is not divisible by 100
, unless it divisible by 400
. This means that over 400
years there are ((365 * 4 + 1) * 25 - 1) * 4 + 1 = 146097
days, which means an average of 365.2425
days per year.