Skip to content

Commit e327137

Browse files
new ordering and equality page
1 parent 23005f2 commit e327137

File tree

4 files changed

+150
-149
lines changed

4 files changed

+150
-149
lines changed

modules/ROOT/content-nav.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
** xref:values-and-types/lists.adoc[]
6666
** xref:values-and-types/maps.adoc[]
6767
** xref:values-and-types/casting-data.adoc[]
68+
** xref:values-and-types/ordering-equality-comparison.adoc[]
69+
6870
6971
* xref:expressions/index.adoc[]
7072
** xref:expressions/expressions-overview.adoc[]

modules/ROOT/pages/expressions/predicate-expressions/operators.adoc

Lines changed: 1 addition & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ The comparison operators comprise:
176176
* `IS NOT NULL`
177177

178178
[TIP]
179-
For more information about `NULL`, see xref:values-and-types/working-with-null.adoc[].
179+
For more information about how Cypher orders and compares different value types, see xref:values-and-types/ordering-equality-comparison.adoc[Values and types -> Equality, ordering, and comparison of value types]
180180

181181
.Comparison operators
182182
=====
@@ -344,154 +344,6 @@ RETURN n.name AS name, n.email AS email
344344
345345
=====
346346

347-
[[equality-and-comparison]]
348-
=== Equality and comparison of values
349-
350-
The equality (`=`) and inequality (`<>`) operators allows for comparing the equality of different values.
351-
352-
Values of the same type are only equal if they are the same identical value (e.g. `3 = 3` and `"x" <> "xy"`).
353-
354-
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]`).
355-
356-
Values of different types are considered as equal according to the following rules:
357-
358-
* `PATH` values are treated as lists of alternating nodes and relationships and are equal to all lists that contain an identical sequence of nodes and relationships.
359-
* Testing any value against `NULL` with either the `=` or `<>` operator always evaluates to `NULL`.
360-
This includes `NULL = NULL` and `NULL <> NULL`.
361-
To reliably test if a value is `NULL` use `v IS NULL` or `v IS NOT NULL` (the latter is equivalent to `NOT(v IS NULL)`).
362-
363-
Other combinations of value types cannot be compared with each other.
364-
For example, nodes, relationships, and literal maps cannot be compared to one another.
365-
Comparing incomparable values will throw an error.
366-
367-
[[ordering-and-comparison]]
368-
=== Ordering and comparison of values
369-
370-
xref:clauses/order-by.adoc[`ORDER BY`] requires that all values are orderable.
371-
The following points explain how comparisons are made when using the `\<=`, `<`,`>=`, `>` operators.
372-
373-
* Numerical values are compared for ordering using numerical order (e.g. `3 < 4` is `TRUE`).
374-
* All comparability tests with `java.lang.Double.NaN` evaluate as `FALSE`.
375-
For example, `1 > b` and `1 < b` are both `FALSE` when `b` is NaN.
376-
* String values are compared for ordering using lexicographic order (e.g. `"x" < "xy"`).
377-
* Boolean values are compared for ordering such that `FALSE < TRUE`.
378-
* When comparing values for ordering, if one of the arguments is `NULL`, the result is always `NULL`.
379-
* xref:values-and-types/spatial.adoc[Spatial values] cannot be compared using the operators `\<=`, `<`,`>=`, `>`.
380-
To compare spatial values within a specific range, use either the xref:functions/spatial.adoc#functions-withinBBox[`point.withinBBox()`] or the xref:functions/spatial.adoc#functions-point-wgs84-2d[`point()`] function.
381-
382-
This section also includes the following categories:
383-
384-
* xref:expressions/predicate-expressions/operators.adoc#value-hierarchy[Hierarchy of values]
385-
* xref:expressions/predicate-expressions/operators.adoc#ordering-lists-maps[Ordering list and map values]
386-
* xref:expressions/predicate-expressions/operators.adoc#ordering-spatial-temporal[Ordering spatial and temporal values]
387-
388-
[[value-hierarchy]]
389-
==== Hierarchy of values
390-
391-
Values of different types are ordered based on a predefined hierarchy, from least to greatest, as outlined in the following list:
392-
393-
* xref::values-and-types/maps.adoc#cypher-literal-maps[`MAP`]
394-
* xref::values-and-types/property-structural-constructed.adoc#structural-types[`NODE`]
395-
* xref::values-and-types/property-structural-constructed.adoc#structural-types[`RELATIONSHIP`]
396-
* xref::values-and-types/lists.adoc[`LIST`]
397-
* xref::patterns/fixed-length-patterns.adoc#path-patterns[`PATH`]
398-
* xref::values-and-types/temporal.adoc[`ZONED DATETIME`]
399-
* xref::values-and-types/temporal.adoc[`LOCAL DATETIME`]
400-
* xref::values-and-types/temporal.adoc[`DATE`]
401-
* xref::values-and-types/temporal.adoc[`ZONED TIME`]
402-
* xref::values-and-types/temporal.adoc[`LOCAL TIME`]
403-
* xref::values-and-types/temporal.adoc[`DURATION`]
404-
* xref::values-and-types/spatial.adoc[`POINT`]
405-
* xref::expressions/expressions-overview.adoc#string[`STRING`]
406-
* xref::expressions/expressions-overview.adoc#boolean[`BOOLEAN`]
407-
* Numbers: xref::expressions/expressions-overview.adoc#numerical[`INTEGER`, `FLOAT`]
408-
409-
[NOTE]
410-
`NULL` is ordered after all other values.
411-
412-
.Sorting rules for mixed Cypher types
413-
[source, cypher]
414-
----
415-
WITH [42, "hello", NULL, true, {name: "Alice"}, [1, 2, 3], date("2024-02-10")] AS v
416-
UNWIND v AS values
417-
RETURN values
418-
ORDER BY values
419-
----
420-
421-
.Result
422-
[role="queryresult",options="header,footer",cols="1*<m"]
423-
|===
424-
| values
425-
426-
| {name: "Alice"}
427-
| [1, 2, 3]
428-
| 2024-02-10
429-
| "hello"
430-
| TRUE
431-
| 42
432-
| NULL
433-
434-
1+d|Rows: 7
435-
436-
|===
437-
438-
[[ordering-lists-maps]]
439-
==== Ordering list and map values
440-
441-
*Lists are compared in lexicographic order:*
442-
443-
* Elements are compared pairwise from the start to the end of the list.
444-
The order is defined by the first pair where the elements differ.
445-
For example, `[1, 'foo', 3]` is less than `[1, 2, 'bar']` because `'foo'` is less than `2`.
446-
* If one list is shorter, it is padded with an empty element, which is considered less than any other value (including `NULL`).
447-
For example, `[1, 'foo']` is less than `[1, 'foo', 3]`, and `[1]` is less than `[1, NULL]`.
448-
449-
*Maps are ordered by size, keys, and values:*
450-
451-
* Maps are compared primarily by size: the smallest map has the fewest entries. For example, `{a: 1}` is less than `{a: 0, b: 'foo'}`.
452-
* Maps of equal size are compared by the alphabetical order of their keys.
453-
For example, `{b: 100, a: 'foo'}` is less than `{a: '', c: NULL}` because `['a', 'b']` is less than `['a', 'c']`.
454-
* For maps with identical key sets, the comparison is based on the values.
455-
After sorting keys alphabetically, values are compared pairwise.
456-
For example, `{b: 100, a: 'foo'}` is less than `{a: 'foo', b: NULL}` because `['foo', 100]` is less than `['foo', NULL]`.
457-
458-
For more information about `LIST` and `MAP` values, see xref::values-and-types/property-structural-constructed.adoc#constructed-types[Values and types -> Constructed types].
459-
460-
[[ordering-spatial-temporal]]
461-
==== Ordering spatial and temporal values
462-
463-
The following applies to the ordering of xref:values-and-types/spatial.adoc[spatial types]:
464-
465-
* `POINT` values are ordered after lists and before temporal types.
466-
* `POINT` values of different coordinate reference systems (CRS) are ordered by the CRS code (the value of SRID field).
467-
For the currently supported set of xref::values-and-types/spatial.adoc#cypher-spatial-crs[CRS], the following ascending order applies: `4326`, `4979`, `7302`, `9157`.
468-
* `POINT` values with the same CRS are ordered by each coordinate value in turn; first `x`, then `y`, and finally `z`.
469-
* Note that this ordering is different to the order returned by the spatial index, which follows the space filling curve.
470-
471-
The following applies to the ordering of xref:values-and-types/temporal.adoc[temporal types]:
472-
473-
* Temporal types are ordered after spatial types but before strings.
474-
* Temporal values follow a chronological order.
475-
For example, `2023-01-01` comes before `2024-01-01`.
476-
* Temporal values are first sorted by type, then by value.
477-
For example, `DATETIME` is considered "greater" than a `DATE` and `2023-02-10T12:00:00` comes before `2023-02-10T15:00:00` because it is chronologically earlier.
478-
* Since there is no perfect way to compare duration values (because months and years have varying lengths), Cypher defines a specific rule for sorting them in `ORDER BY`:
479-
** 1 year is treated as 365.2425 days (to account for leap years).
480-
** 1 month is treated as 30.436875 days (which is 1/12 of a year).
481-
** 1 day is always 24 hours.
482-
483-
The following applies to the comparison of temporal types:
484-
485-
* xref::values-and-types/temporal.adoc#cypher-temporal-instants[Temporal instant values] (like `DATETIME` and `DATE`) can be compared if they are of the same type.
486-
An earlier instant is considered smaller (less than) compared to a later instant.
487-
* Instants at the same point in time but with different time zones are not considered equal.
488-
To ensure consistent ordering, Cypher sorts them first by their actual point in time.
489-
If two instants have the same time but different time zones, they are ordered by their UTC offset (west to east, meaning negative offsets come first).
490-
If they have the same time and offset but different named time zones, they are sorted alphabetically by the time zone name.
491-
* Duration values cannot be directly compared.
492-
Since the length of a day, month, or year varies, Cypher does not define a strict ordering for durations.
493-
As a result, comparing two durations `(e.g, duration1 < duration2)` will always return `NULL`.
494-
495347
[[chaining-comparison-oeprators]]
496348
=== Chaining comparison operators
497349

modules/ROOT/pages/values-and-types/index.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ More information about the data values and types supported by Cypher can be foun
1414
* xref::values-and-types/lists.adoc[]
1515
* xref::values-and-types/maps.adoc[]
1616
* xref::values-and-types/casting-data.adoc[]
17+
* xref:values-and-types/ordering-equality-comparison.adoc[]
1718
1819
[TIP]
1920
For information about how to check the type of a value, see xref:expressions/predicate-expressions/type-predicate-expressions.adoc[]
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
= Equality, ordering, and comparison of value types
2+
:description: Information about how Cypher compares and orders different value types, including equality and inequality rules.
3+
4+
This page explains how Cypher compares and orders different value types, including equality and inequality rules.
5+
6+
[[equality-and-comparison]]
7+
== Equality and comparison of values
8+
9+
The xref:expressions/predicate-expressions/operators.adoc#comparison-operators[equality (`=`) and inequality (`<>`) operators] allows for comparing the equality of different values.
10+
11+
Values of the same type are only equal if they are the same identical value (e.g. `3 = 3` and `"x" <> "xy"`).
12+
13+
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]`).
14+
15+
Values of different types are considered as equal according to the following rules:
16+
17+
* `PATH` values are treated as lists of alternating nodes and relationships and are equal to all lists that contain an identical sequence of nodes and relationships.
18+
* Testing any value against `NULL` with either the `=` or `<>` operator always evaluates to `NULL`.
19+
This includes `NULL = NULL` and `NULL <> NULL`.
20+
To reliably test if a value is `NULL` use `v IS NULL` or `v IS NOT NULL` (the latter is equivalent to `NOT(v IS NULL)`).
21+
22+
Other combinations of value types cannot be compared with each other.
23+
For example, nodes, relationships, and literal maps cannot be compared to one another.
24+
Comparing incomparable values will throw an error.
25+
26+
[[ordering-and-comparison]]
27+
== Ordering and comparison of values
28+
29+
xref:clauses/order-by.adoc[`ORDER BY`] requires that all values are orderable.
30+
The following points explain how comparisons are made when using the `\<=`, `<`,`>=`, `>` operators.
31+
32+
* Numerical values are compared for ordering using numerical order (e.g. `3 < 4` is `TRUE`).
33+
* All comparability tests with `java.lang.Double.NaN` evaluate as `FALSE`.
34+
For example, `1 > b` and `1 < b` are both `FALSE` when `b` is NaN.
35+
* String values are compared for ordering using lexicographic order (e.g. `"x" < "xy"`).
36+
* Boolean values are compared for ordering such that `FALSE < TRUE`.
37+
* When comparing values for ordering, if one of the arguments is `NULL`, the result is always `NULL`.
38+
* xref:values-and-types/spatial.adoc[Spatial values] cannot be compared using the operators `\<=`, `<`,`>=`, `>`.
39+
To compare spatial values within a specific range, use either the xref:functions/spatial.adoc#functions-withinBBox[`point.withinBBox()`] or the xref:functions/spatial.adoc#functions-point-wgs84-2d[`point()`] function.
40+
41+
[[value-hierarchy]]
42+
=== Hierarchy of values
43+
44+
Values of different types are ordered based on a predefined hierarchy, from least to greatest, as outlined in the following list:
45+
46+
* xref::values-and-types/maps.adoc#cypher-literal-maps[`MAP`]
47+
* xref::values-and-types/property-structural-constructed.adoc#structural-types[`NODE`]
48+
* xref::values-and-types/property-structural-constructed.adoc#structural-types[`RELATIONSHIP`]
49+
* xref::values-and-types/lists.adoc[`LIST`]
50+
* xref::patterns/fixed-length-patterns.adoc#path-patterns[`PATH`]
51+
* xref::values-and-types/temporal.adoc[`ZONED DATETIME`]
52+
* xref::values-and-types/temporal.adoc[`LOCAL DATETIME`]
53+
* xref::values-and-types/temporal.adoc[`DATE`]
54+
* xref::values-and-types/temporal.adoc[`ZONED TIME`]
55+
* xref::values-and-types/temporal.adoc[`LOCAL TIME`]
56+
* xref::values-and-types/temporal.adoc[`DURATION`]
57+
* xref::values-and-types/spatial.adoc[`POINT`]
58+
* xref::expressions/expressions-overview.adoc#string[`STRING`]
59+
* xref::expressions/expressions-overview.adoc#boolean[`BOOLEAN`]
60+
* Numbers: xref::expressions/expressions-overview.adoc#numerical[`INTEGER`, `FLOAT`]
61+
62+
[NOTE]
63+
`NULL` is ordered after all other values.
64+
65+
.Sorting rules for mixed Cypher types
66+
[source, cypher]
67+
----
68+
WITH [42, "hello", NULL, true, {name: "Alice"}, [1, 2, 3], date("2024-02-10")] AS v
69+
UNWIND v AS values
70+
RETURN values
71+
ORDER BY values
72+
----
73+
74+
.Result
75+
[role="queryresult",options="header,footer",cols="1*<m"]
76+
|===
77+
| values
78+
79+
| {name: "Alice"}
80+
| [1, 2, 3]
81+
| 2024-02-10
82+
| "hello"
83+
| TRUE
84+
| 42
85+
| NULL
86+
87+
1+d|Rows: 7
88+
89+
|===
90+
91+
[[ordering-lists-maps]]
92+
=== Ordering list and map values
93+
94+
*Lists are compared in lexicographic order:*
95+
96+
* Elements are compared pairwise from the start to the end of the list.
97+
The order is defined by the first pair where the elements differ.
98+
For example, `[1, 'foo', 3]` is less than `[1, 2, 'bar']` because `'foo'` is less than `2`.
99+
* If one list is shorter, it is padded with an empty element, which is considered less than any other value (including `NULL`).
100+
For example, `[1, 'foo']` is less than `[1, 'foo', 3]`, and `[1]` is less than `[1, NULL]`.
101+
102+
*Maps are ordered by size, keys, and values:*
103+
104+
* Maps are compared primarily by size: the smallest map has the fewest entries. For example, `{a: 1}` is less than `{a: 0, b: 'foo'}`.
105+
* Maps of equal size are compared by the alphabetical order of their keys.
106+
For example, `{b: 100, a: 'foo'}` is less than `{a: '', c: NULL}` because `['a', 'b']` is less than `['a', 'c']`.
107+
* For maps with identical key sets, the comparison is based on the values.
108+
After sorting keys alphabetically, values are compared pairwise.
109+
For example, `{b: 100, a: 'foo'}` is less than `{a: 'foo', b: NULL}` because `['foo', 100]` is less than `['foo', NULL]`.
110+
111+
For more information about `LIST` and `MAP` values, see xref::values-and-types/property-structural-constructed.adoc#constructed-types[Values and types -> Constructed types].
112+
113+
[[ordering-spatial-temporal]]
114+
=== Ordering spatial and temporal values
115+
116+
The following applies to the ordering of xref:values-and-types/spatial.adoc[spatial types]:
117+
118+
* `POINT` values are ordered after lists and before temporal types.
119+
* `POINT` values of different coordinate reference systems (CRS) are ordered by the CRS code (the value of SRID field).
120+
For the currently supported set of xref::values-and-types/spatial.adoc#cypher-spatial-crs[CRS], the following ascending order applies: `4326`, `4979`, `7302`, `9157`.
121+
* `POINT` values with the same CRS are ordered by each coordinate value in turn; first `x`, then `y`, and finally `z`.
122+
* Note that this ordering is different to the order returned by the spatial index, which follows the space filling curve.
123+
124+
The following applies to the ordering of xref:values-and-types/temporal.adoc[temporal types]:
125+
126+
* Temporal types are ordered after spatial types but before strings.
127+
* Temporal values follow a chronological order.
128+
For example, `2023-01-01` comes before `2024-01-01`.
129+
* Temporal values are first sorted by type, then by value.
130+
For example, `DATETIME` is considered "greater" than a `DATE` and `2023-02-10T12:00:00` comes before `2023-02-10T15:00:00` because it is chronologically earlier.
131+
* Since there is no perfect way to compare duration values (because months and years have varying lengths), Cypher defines a specific rule for sorting them in `ORDER BY`:
132+
** 1 year is treated as 365.2425 days (to account for leap years).
133+
** 1 month is treated as 30.436875 days (which is 1/12 of a year).
134+
** 1 day is always 24 hours.
135+
136+
The following applies to the comparison of temporal types:
137+
138+
* xref::values-and-types/temporal.adoc#cypher-temporal-instants[Temporal instant values] (like `DATETIME` and `DATE`) can be compared if they are of the same type.
139+
An earlier instant is considered smaller (less than) compared to a later instant.
140+
* Instants at the same point in time but with different time zones are not considered equal.
141+
To ensure consistent ordering, Cypher sorts them first by their actual point in time.
142+
If two instants have the same time but different time zones, they are ordered by their UTC offset (west to east, meaning negative offsets come first).
143+
If they have the same time and offset but different named time zones, they are sorted alphabetically by the time zone name.
144+
* Duration values cannot be directly compared.
145+
Since the length of a day, month, or year varies, Cypher does not define a strict ordering for durations.
146+
As a result, comparing two durations `(e.g, duration1 < duration2)` will always return `NULL`.

0 commit comments

Comments
 (0)