Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/ROOT/content-nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
*** xref:expressions/predicates/path-pattern-expressions.adoc[]
*** xref:expressions/predicates/type-predicate-expressions.adoc[]
** xref:expressions/mathematical-operators.adoc[]
** xref:expressions/string-operators.adoc[]
** xref:expressions/conditional-expressions.adoc[]

* xref:functions/index.adoc[]
Expand Down
2 changes: 2 additions & 0 deletions modules/ROOT/pages/expressions/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ For details and examples of specific expressions, see the following sections:
** xref:expressions/predicates/path-pattern-expressions.adoc[]: information about filtering queries with path pattern expressions.
** xref:expressions/predicates/type-predicate-expressions.adoc[]: information about how to verify the value type of a Cypher expression.
* xref:expressions/mathematical-operators.adoc[]: `+`, `-`, `*`, `/`, `%`, `^`.
* xref:expressions/string-operators.adoc[]: `+`, `||`
* xref:expressions/conditional-expressions.adoc[]

226 changes: 226 additions & 0 deletions modules/ROOT/pages/expressions/string-operators.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
= String concatenation operators
:description: Information about Cypher's string concatenation operators.
:table-caption!:

Cypher contains two operators for the concatenation of `STRING` values:

* `||`
* `+`

The two operators are functionally equivalent.
However, `||` is xref:appendix/gql-conformance/index.adoc[GQL conformant], while `+` is not.

For additional expressions that evaluate to `STRING` values, see xref:functions/string.adoc[String functions].

[[examples]]
== Examples

.`||` and `+`
[source, cypher]
----
RETURN 'Neo' || '4j' AS result1,
'Neo' + '4j' AS result2
----

.Result
[role="queryresult",options="header,footer",cols="2*<m"]
|===
| result1 | result2

| "Neo4j" | "Neo4j"

2+d|Rows: 1
|===

The xref:functions/string.adoc#functions-tostring[`toString()`] function can be used to concatenate non-`STRING` values into a `STRING` value.

.Concatenation using `toString()` function
[source, cypher]
----
RETURN 'The number is: ' || toString(42) AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result

| "The number is: 42"

1+d| Rows: 1
|===

Cypher does not insert spaces when concatenating `STRING` values.

.Adding whitespaces in `STRING` concatenation
[source, cypher]
----
RETURN 'Alpha' || 'Beta' AS result1,
'Alpha' || ' ' || 'Beta' AS result2
----

.Result
[role="queryresult",options="header,footer",cols="2*<m"]
|===
| result1 | result2

| "AlphaBeta" | "Alpha Beta"

2+d| Rows: 1
|===

.Concatenating `STRING` properties
[source, cypher]
----
CREATE (p:Person {firstName: 'Keanu', lastName: 'Reeves'})
SET p.fullName = p.firstName || ' ' || p.lastName
RETURN p.fullName AS fullName
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| fullName

| "Keanu Reeves"

1+d| Rows: 1
|===

.Adding separators in `STRING` concatenation
[source, cypher]
----
RETURN 'Hello' || ', ' || 'World' AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result

| "Hello, World"

1+d| Rows: 1
|===

.Adding prefix, suffix, and separators in `STRING` concatenation
[source, cypher]
----
RETURN 'My favorite fruits are: ' || 'apples' || ', ' || 'bananas' || ', and' || 'oranges' || '.' AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result

| "My favorite fruits are: apples, bananas, and oranges."

1+d| Rows: 1
|===

[[list-values-and-null]]
== String concatenation, `LIST` values, and `NULL`

`STRING` values in a `LIST` can be concatenated using the xref:functions/list.adoc#functions-reduce[`reduce()`] function.

.Concatenate `STRING` values in a `LIST`
[source, cypher]
----
WITH ['Neo', '4j'] AS list
RETURN reduce(acc = '', item IN list| acc || item) AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result

| "Neo4j"

1+d| Rows: 1
|===

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`.
The `reduce()` function then concatenates these items with commas.

.Add prefix and a separator (`,`) in a `STRING` concatenated from `STRING` values in a `LIST`
[source, cypher]
----
WITH ['Apples', 'Bananas', 'Oranges'] AS list
RETURN 'My favorite fruits are: ' || reduce(acc = head(list), item IN tail(list) | acc || ', ' || item) || '.' AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result

| "My favorite fruits are: Apples, Bananas, Oranges."

1+d| Rows: 1
|===

Concatenating a `STRING` value with `NULL` returns `NULL`.
To skip the first `NULL` value in a list of expressions, use the xref:functions/scalar.adoc#functions-coalesce[`coalesce()`] function.

In the following query, `coalesce()` is used with `reduce()` to replace each `NULL` value in the `LIST` with an empty `STRING` (`''`).
This ensures that all `NULL` values are effectively skipped, allowing the `reduce()` function to concatenate the remaining `STRING` values.

.Using `reduce()` and `coalesce()` to skip `NULL` values when concatenating a `LIST`
[source, cypher]
----
WITH ['Apples', NULL, 'Bananas', NULL, 'Oranges', NULL] AS list
RETURN 'My favorite fruits are: ' || reduce(acc = head(list), item IN tail(list) | acc || coalesce(', ' || item, '')) || '.' AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result

| "My favorite fruits are: Apples, Bananas, Oranges."

1+d|Rows: 1
|===

If a `LIST` is empty, `reduce()` will return `NULL` because there are no elements to process.
In such cases, `coalesce()` can be used to replace the `NULL` with a default value (e.g., `'none'`).

.Using `reduce()` and `coalesce()` to handle empty `LIST` values
[source, cypher]
----
UNWIND [['Apples', 'Bananas', 'Oranges'], ['Pears'], []] AS list
RETURN 'My favorite fruits are: ' || coalesce(reduce(acc = head(list), item IN tail(list) | acc || ', ' || item), 'none') || '.' AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result

| "My favorite fruits are: Apples, Bananas, Oranges."
| "My favorite fruits are: Pears."
| "My favorite fruits are: none."

1+d|Rows: 3
|===

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.

.List comprehension with `STRING` concatenation on `LIST` items
[source, cypher]
----
WITH ['Apples', 'Bananas', 'Oranges'] AS list
RETURN [item IN list | 'Eat more ' || item || '!'] AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result

| ["Eat more Apples!", "Eat more Bananas!", "Eat more Oranges!"]

1+d| Rows: 1
|===
2 changes: 1 addition & 1 deletion modules/ROOT/pages/functions/string.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ When `toString()` is applied to a temporal value, it returns a `STRING` represen
This `STRING` will therefore be formatted according to the https://en.wikipedia.org/wiki/ISO_8601[ISO 8601] format.
====

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


[[functions-btrim]]
Expand Down
50 changes: 0 additions & 50 deletions modules/ROOT/pages/syntax/operators.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ This page contains an overview of the available Cypher operators.
|===
| xref::syntax/operators.adoc#query-operators-aggregation[Aggregation operators] | `DISTINCT`
| 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
| xref::syntax/operators.adoc#query-operators-string[String operators] | `+` and `\|\|` (string concatenation), `IS NORMALIZED`
| 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
| xref::syntax/operators.adoc#query-operators-map[Map operators] | `.` for static value access by key, `[]` for dynamic value access by key
| 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
Expand Down Expand Up @@ -188,55 +187,6 @@ The properties on the node are updated as follows by those provided in the map:

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 `+=`.

[[query-operators-string]]
== String operators

The string operators comprise:

* concatenating `STRING` values: `+` and `||`
* checking if a `STRING` is normalized: `IS NORMALIZED`

[[syntax-concatenating-two-strings]]
=== Concatenating two `STRING` values with `+`

Using `+` to concatenate strings is functionally equivalent to using `||`.
However, the `+` string concatenation operator is not xref:appendix/gql-conformance/index.adoc[GQL conformant].

.Query
[source, cypher]
----
RETURN 'neo' + '4j' AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| +result+
| +"neo4j"+

1+d|Rows: 1
|===


[[syntax-concatenating-two-strings-doublebar]]
=== Concatenating two `STRING` values with `||`


.Query
[source, cypher]
----
RETURN 'neo' || '4j' AS result
----

.Result
[role="queryresult",options="header,footer",cols="1*<m"]
|===
| result
| "neo4j"
1+d|Rows: 1
|===


[[query-operators-temporal]]
== Temporal operators

Expand Down