Skip to content

Commit 9d39c40

Browse files
String expressions (#1215)
1 parent 7d615a2 commit 9d39c40

File tree

5 files changed

+230
-51
lines changed

5 files changed

+230
-51
lines changed

modules/ROOT/content-nav.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
*** xref:expressions/predicates/path-pattern-expressions.adoc[]
7575
*** xref:expressions/predicates/type-predicate-expressions.adoc[]
7676
** xref:expressions/mathematical-operators.adoc[]
77+
** xref:expressions/string-operators.adoc[]
7778
** xref:expressions/conditional-expressions.adoc[]
7879
7980
* xref:functions/index.adoc[]

modules/ROOT/pages/expressions/index.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ For details and examples of specific expressions, see the following sections:
1212
** xref:expressions/predicates/path-pattern-expressions.adoc[]: information about filtering queries with path pattern expressions.
1313
** xref:expressions/predicates/type-predicate-expressions.adoc[]: information about how to verify the value type of a Cypher expression.
1414
* xref:expressions/mathematical-operators.adoc[]: `+`, `-`, `*`, `/`, `%`, `^`.
15+
* xref:expressions/string-operators.adoc[]: `+`, `||`
1516
* xref:expressions/conditional-expressions.adoc[]
17+
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
= String concatenation operators
2+
:description: Information about Cypher's string concatenation operators.
3+
:table-caption!:
4+
5+
Cypher contains two operators for the concatenation of `STRING` values:
6+
7+
* `||`
8+
* `+`
9+
10+
The two operators are functionally equivalent.
11+
However, `||` is xref:appendix/gql-conformance/index.adoc[GQL conformant], while `+` is not.
12+
13+
For additional expressions that evaluate to `STRING` values, see xref:functions/string.adoc[String functions].
14+
15+
[[examples]]
16+
== Examples
17+
18+
.`||` and `+`
19+
[source, cypher]
20+
----
21+
RETURN 'Neo' || '4j' AS result1,
22+
'Neo' + '4j' AS result2
23+
----
24+
25+
.Result
26+
[role="queryresult",options="header,footer",cols="2*<m"]
27+
|===
28+
| result1 | result2
29+
30+
| "Neo4j" | "Neo4j"
31+
32+
2+d|Rows: 1
33+
|===
34+
35+
The xref:functions/string.adoc#functions-tostring[`toString()`] function can be used to concatenate non-`STRING` values into a `STRING` value.
36+
37+
.Concatenation using `toString()` function
38+
[source, cypher]
39+
----
40+
RETURN 'The number is: ' || toString(42) AS result
41+
----
42+
43+
.Result
44+
[role="queryresult",options="header,footer",cols="1*<m"]
45+
|===
46+
| result
47+
48+
| "The number is: 42"
49+
50+
1+d| Rows: 1
51+
|===
52+
53+
Cypher does not insert spaces when concatenating `STRING` values.
54+
55+
.Adding whitespaces in `STRING` concatenation
56+
[source, cypher]
57+
----
58+
RETURN 'Alpha' || 'Beta' AS result1,
59+
'Alpha' || ' ' || 'Beta' AS result2
60+
----
61+
62+
.Result
63+
[role="queryresult",options="header,footer",cols="2*<m"]
64+
|===
65+
| result1 | result2
66+
67+
| "AlphaBeta" | "Alpha Beta"
68+
69+
2+d| Rows: 1
70+
|===
71+
72+
.Concatenating `STRING` properties
73+
[source, cypher]
74+
----
75+
CREATE (p:Person {firstName: 'Keanu', lastName: 'Reeves'})
76+
SET p.fullName = p.firstName || ' ' || p.lastName
77+
RETURN p.fullName AS fullName
78+
----
79+
80+
.Result
81+
[role="queryresult",options="header,footer",cols="1*<m"]
82+
|===
83+
| fullName
84+
85+
| "Keanu Reeves"
86+
87+
1+d| Rows: 1
88+
|===
89+
90+
.Adding separators in `STRING` concatenation
91+
[source, cypher]
92+
----
93+
RETURN 'Hello' || ', ' || 'World' AS result
94+
----
95+
96+
.Result
97+
[role="queryresult",options="header,footer",cols="1*<m"]
98+
|===
99+
| result
100+
101+
| "Hello, World"
102+
103+
1+d| Rows: 1
104+
|===
105+
106+
.Adding prefix, suffix, and separators in `STRING` concatenation
107+
[source, cypher]
108+
----
109+
RETURN 'My favorite fruits are: ' || 'apples' || ', ' || 'bananas' || ', and' || 'oranges' || '.' AS result
110+
----
111+
112+
.Result
113+
[role="queryresult",options="header,footer",cols="1*<m"]
114+
|===
115+
| result
116+
117+
| "My favorite fruits are: apples, bananas, and oranges."
118+
119+
1+d| Rows: 1
120+
|===
121+
122+
[[list-values-and-null]]
123+
== String concatenation, `LIST` values, and `NULL`
124+
125+
`STRING` values in a `LIST` can be concatenated using the xref:functions/list.adoc#functions-reduce[`reduce()`] function.
126+
127+
.Concatenate `STRING` values in a `LIST`
128+
[source, cypher]
129+
----
130+
WITH ['Neo', '4j'] AS list
131+
RETURN reduce(acc = '', item IN list| acc || item) AS result
132+
----
133+
134+
.Result
135+
[role="queryresult",options="header,footer",cols="1*<m"]
136+
|===
137+
| result
138+
139+
| "Neo4j"
140+
141+
1+d| Rows: 1
142+
|===
143+
144+
The following query uses the xref:functions/scalar.adoc#functions-head[`head()`] function to start the accumulator with the first `item` in the `list`, while the xref:functions/scalar.adoc#functions-tail[`tail()`] function returns the remaining items in the `list`.
145+
The `reduce()` function then concatenates these items with commas.
146+
147+
.Add prefix and a separator (`,`) in a `STRING` concatenated from `STRING` values in a `LIST`
148+
[source, cypher]
149+
----
150+
WITH ['Apples', 'Bananas', 'Oranges'] AS list
151+
RETURN 'My favorite fruits are: ' || reduce(acc = head(list), item IN tail(list) | acc || ', ' || item) || '.' AS result
152+
----
153+
154+
.Result
155+
[role="queryresult",options="header,footer",cols="1*<m"]
156+
|===
157+
| result
158+
159+
| "My favorite fruits are: Apples, Bananas, Oranges."
160+
161+
1+d| Rows: 1
162+
|===
163+
164+
Concatenating a `STRING` value with `NULL` returns `NULL`.
165+
To skip the first `NULL` value in a list of expressions, use the xref:functions/scalar.adoc#functions-coalesce[`coalesce()`] function.
166+
167+
In the following query, `coalesce()` is used with `reduce()` to replace each `NULL` value in the `LIST` with an empty `STRING` (`''`).
168+
This ensures that all `NULL` values are effectively skipped, allowing the `reduce()` function to concatenate the remaining `STRING` values.
169+
170+
.Using `reduce()` and `coalesce()` to skip `NULL` values when concatenating a `LIST`
171+
[source, cypher]
172+
----
173+
WITH ['Apples', NULL, 'Bananas', NULL, 'Oranges', NULL] AS list
174+
RETURN 'My favorite fruits are: ' || reduce(acc = head(list), item IN tail(list) | acc || coalesce(', ' || item, '')) || '.' AS result
175+
----
176+
177+
.Result
178+
[role="queryresult",options="header,footer",cols="1*<m"]
179+
|===
180+
| result
181+
182+
| "My favorite fruits are: Apples, Bananas, Oranges."
183+
184+
1+d|Rows: 1
185+
|===
186+
187+
If a `LIST` is empty, `reduce()` will return `NULL` because there are no elements to process.
188+
In such cases, `coalesce()` can be used to replace the `NULL` with a default value (e.g., `'none'`).
189+
190+
.Using `reduce()` and `coalesce()` to handle empty `LIST` values
191+
[source, cypher]
192+
----
193+
UNWIND [['Apples', 'Bananas', 'Oranges'], ['Pears'], []] AS list
194+
RETURN 'My favorite fruits are: ' || coalesce(reduce(acc = head(list), item IN tail(list) | acc || ', ' || item), 'none') || '.' AS result
195+
----
196+
197+
.Result
198+
[role="queryresult",options="header,footer",cols="1*<m"]
199+
|===
200+
| result
201+
202+
| "My favorite fruits are: Apples, Bananas, Oranges."
203+
| "My favorite fruits are: Pears."
204+
| "My favorite fruits are: none."
205+
206+
1+d|Rows: 3
207+
|===
208+
209+
Additionally, xref:values-and-types/lists.adoc#cypher-list-comprehension[list comprehension] allows concatenating a `STRING` value to each item in a `LIST` to generate a new `LIST` of modified `STRING` values.
210+
211+
.List comprehension with `STRING` concatenation on `LIST` items
212+
[source, cypher]
213+
----
214+
WITH ['Apples', 'Bananas', 'Oranges'] AS list
215+
RETURN [item IN list | 'Eat more ' || item || '!'] AS result
216+
----
217+
218+
.Result
219+
[role="queryresult",options="header,footer",cols="1*<m"]
220+
|===
221+
| result
222+
223+
| ["Eat more Apples!", "Eat more Bananas!", "Eat more Oranges!"]
224+
225+
1+d| Rows: 1
226+
|===

modules/ROOT/pages/functions/string.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ When `toString()` is applied to a temporal value, it returns a `STRING` represen
1616
This `STRING` will therefore be formatted according to the https://en.wikipedia.org/wiki/ISO_8601[ISO 8601] format.
1717
====
1818

19-
See also xref::syntax/operators.adoc#query-operators-string[String operators].
19+
See also xref::expressions/string-operators.adoc[String concatenation operators].
2020

2121

2222
[[functions-btrim]]

modules/ROOT/pages/syntax/operators.adoc

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ This page contains an overview of the available Cypher operators.
1212
|===
1313
| xref::syntax/operators.adoc#query-operators-aggregation[Aggregation operators] | `DISTINCT`
1414
| xref::syntax/operators.adoc#query-operators-property[Property operators] | `.` for static property access, `[]` for dynamic property access, `=` for replacing all properties, `+=` for mutating specific properties
15-
| xref::syntax/operators.adoc#query-operators-string[String operators] | `+` and `\|\|` (string concatenation), `IS NORMALIZED`
1615
| xref::syntax/operators.adoc#query-operators-temporal[Temporal operators] | `+` and `-` for operations between durations and temporal instants/durations, `*` and `/` for operations between durations and numbers
1716
| xref::syntax/operators.adoc#query-operators-map[Map operators] | `.` for static value access by key, `[]` for dynamic value access by key
1817
| xref::syntax/operators.adoc#query-operators-list[List operators] | `+` and `\|\|` (list concatenation), `IN` to check existence of an element in a list, `[]` for accessing element(s) dynamically
@@ -188,55 +187,6 @@ The properties on the node are updated as follows by those provided in the map:
188187

189188
See xref::clauses/set.adoc#set-setting-properties-using-map[Mutate specific properties using a map and `+=`] for more details on using the property mutation operator `+=`.
190189

191-
[[query-operators-string]]
192-
== String operators
193-
194-
The string operators comprise:
195-
196-
* concatenating `STRING` values: `+` and `||`
197-
* checking if a `STRING` is normalized: `IS NORMALIZED`
198-
199-
[[syntax-concatenating-two-strings]]
200-
=== Concatenating two `STRING` values with `+`
201-
202-
Using `+` to concatenate strings is functionally equivalent to using `||`.
203-
However, the `+` string concatenation operator is not xref:appendix/gql-conformance/index.adoc[GQL conformant].
204-
205-
.Query
206-
[source, cypher]
207-
----
208-
RETURN 'neo' + '4j' AS result
209-
----
210-
211-
.Result
212-
[role="queryresult",options="header,footer",cols="1*<m"]
213-
|===
214-
| +result+
215-
| +"neo4j"+
216-
217-
1+d|Rows: 1
218-
|===
219-
220-
221-
[[syntax-concatenating-two-strings-doublebar]]
222-
=== Concatenating two `STRING` values with `||`
223-
224-
225-
.Query
226-
[source, cypher]
227-
----
228-
RETURN 'neo' || '4j' AS result
229-
----
230-
231-
.Result
232-
[role="queryresult",options="header,footer",cols="1*<m"]
233-
|===
234-
| result
235-
| "neo4j"
236-
1+d|Rows: 1
237-
|===
238-
239-
240190
[[query-operators-temporal]]
241191
== Temporal operators
242192

0 commit comments

Comments
 (0)