# Expressions

The following sections describe some of the other supported features.

## String operators

Apart from comparison and concatenation operators Cypher provides special
string operators for easier matching of substrings:

| Operator          | Description                                                      |
| ----------------- | ---------------------------------------------------------------- |
| `a STARTS WITH b` | Returns true if the prefix of string a is equal to string b.     |
| `a ENDS WITH b`   | Returns true if the suffix of string a is equal to string b.     |
| `a CONTAINS b`    | Returns true if some substring of string a is equal to string b. |

For example, if you want to return the names of all `Person` nodes where the name starts with `Joh` the query would be:

```cypher
MATCH (p:Person)
WHERE p.name STARTS WITH 'Joh'
RETURN p.name;
```

## Parameters

When automating the queries for Memgraph, it comes in handy to change only some
parts of the query. Usually, these parts are values that are used for filtering
results or similar, while the rest of the query remains the same.

Parameters allow reusing the same query but with different parameter values.
They are indicated using the `$` symbol followed by the parameter name (e.g.,
`$name`, `$limit`). 

> **Info**
>
> Memgraph **does not** support the old Cypher syntax using curly braces (e.g.,
>    `{param}`).
>
>    The parameters described here are **client-supplied** — they are sent with
>    each query via the Bolt protocol and exist only for the duration of that
>    query. If you need named values that **persist across sessions**, see
>    [Server-side parameters](https://memgraph.com/docs/database-management/server-side-parameters).

Below are some examples of the usage of parameters in Memgraph.

### Common examples

**Filtering node properties**

```cypher
MATCH (node {property: $propertyValue}) RETURN node;
```

**Updating node properties**

```cypher
MATCH (n) SET n.propertyValue = $propertyNewValue;
```

**Using parameters in LIMIT clauses**

Memgraph also supports parameters in `LIMIT` clauses. For example:

```cypher
MATCH (n) 
RETURN n 
LIMIT $limit;
```

**Using parameters with `LOAD CSV`**

Additionally, Memgraph supports parameters for LOAD CSV queries. For instance:

```cypher
LOAD CSV FROM $file AS row 
CREATE (:Node {property: row.property});
```

### Label parameterization

Starting from version 3.1, Memgraph allows node labels to be created using
expressions of type `String` or `List[String]`. 

**Static label parameterization**

You can use parameters instead of any literal in the query. For example, if you
want to filter nodes based on a specific label, you can execute the following
query:

```cypher
MATCH (n:$label)
RETURN n;
```

**Dynamic label parameterization**

You can dynamically assign multiple labels to a node using parameters:

```cypher
MATCH (n)
SET n:$labels;
```

Given the following parameter:

```json
{
  "labels": ["Person", "Student"]
}
```

### Using property maps

Memgraph supports property maps **in some clauses**. For example:

**Supported (e.g., in `CREATE`)**

```cypher
CREATE (n $propertyMap) 
RETURN n;
```

**Not supported (e.g., in `MATCH` or `MERGE`):**

```cypher
MATCH (n $propertyMap) 
RETURN n;
```

### Usage with Python driver

To use parameters with a Python driver, use the following syntax:

```python
session.run(
   'CREATE (alice:Person {name: $name, age: $ageValue})',
   name='Alice', ageValue=22
).consume()
```

To do the same with labels:

```python
session.run(
   'CREATE (alice:$label {name: $name, age: $ageValue}',
   label='Person', name='Alice', ageValue=22
).consume()
```

To use a property map as a parameter, you can use the following syntax:

```python
session.run(
   'CREATE (alice:Person $propertyMap)', 
   propertymap={"name": "Alice"}
).consume()
```

To use parameters whose names are integers, you will need to wrap parameters in
a dictionary and convert them to strings before running a query:

```python
session.run(
   'CREATE (alice:Person {name: $0, age: $1})',
   {'0': "Alice", '1': 22}
).consume()
```

To use parameters with some other driver, please consult the appropriate
documentation.

## CASE

Conditional expressions can be expressed in the Cypher language with the `CASE`
expression. A simple form is used to compare an expression against multiple
predicates. For the first matched predicate result of the expression provided
after the `THEN` keyword is returned. If no expression is matched value
following `ELSE` is returned is provided, or `null` if `ELSE` is not used:

```cypher
MATCH (n)
RETURN CASE n.currency WHEN "DOLLAR" THEN "$" WHEN "EURO" THEN "€" ELSE "UNKNOWN" END;
```

In generic form, you don't need to provide an expression whose value is compared
to predicates, but you can list multiple predicates and the first one that
evaluates to true is matched:

```cypher
MATCH (n)
RETURN CASE WHEN n.height < 30 THEN "short" WHEN n.height > 300 THEN "tall" END;
```

Most expressions that take `null` as input will produce `null`. This includes boolean expressions that are used as
predicates. In this case, anything that is not true is interpreted as being false. This also concludes that logically `null!=null`.

The [`exists()`](https://memgraph.com/docs/querying/functions#pattern-functions) function and the `EXISTS { … }`, `COUNT { … }` and
`COLLECT { … }` [subquery expressions](https://memgraph.com/docs/querying/subquery-expressions) can all be used inside `CASE`.

## Pattern existence (exists(pattern))

`exists(pattern)` is a short form for a simple pattern existence check. It is accepted in the same
positions as `EXISTS { … }` — see [where you can use a subquery
expression](https://memgraph.com/docs/querying/subquery-expressions#where-you-can-use-a-subquery-expression). For a
dataset-backed example, see [Filter with EXISTS
expressions](https://memgraph.com/docs/querying/clauses/where#17-filter-with-exists-expressions).

## Subquery expressions (EXISTS, COUNT, COLLECT)

`EXISTS { … }` tests whether a subquery body produces any rows, `COUNT { … }` returns how many it
produces, and `COLLECT { … }` gathers its single return column into a list. All three run the body once
per row of the enclosing query and may correlate with the enclosing query's variables. See [Subquery
expressions](https://memgraph.com/docs/querying/subquery-expressions) for the positions they are accepted in and the rules their
bodies follow.

For `EXISTS` used specifically as a filter, see [Existential subqueries in
WHERE](https://memgraph.com/docs/querying/clauses/where#4-existential-subqueries).

## Pattern comprehension

Pattern comprehension is a syntactic construct available in Cypher for creating a list based on matchings of a pattern.
A pattern comprehension matches the specified pattern like a normal `MATCH` clause, with predicates like a normal `WHERE` clause,
but yields a custom projection as specified.

For example, if you want to get person names along with the release years and titles of all the movies with `Matrix` in their title that they
are related to the query would be:

```cypher
MATCH (n:Person)
RETURN n.name,
    [(n)-->(b:Movie) WHERE b.title CONTAINS 'Matrix' | b.released] AS years,
    [(n)-->(c:Movie) WHERE c.title CONTAINS 'Matrix' | c.title] AS titles;
```

For example, the following query finds person names with more than 5 characters, treats them as `actors`, and extracts the titles and releases years
of the movies they're linked to (provided those movies were released after the year 2000), then returns all this information as lists,
alongside the corresponding actor's name.

```cypher
MATCH (n:Person) WHERE size(n.name) > 5
WITH
    n AS actor,
    [(n)-->(m) WHERE m.released > 2000 | m.title] AS titles,
    [(n)-->(m) WHERE m.released > 2000 | m.released] AS years
RETURN actor.name, years, titles;
```
The whole predicate, including the `WHERE` keyword, is optional and may be omitted.

Pattern comprehensions can be nested, for example `[(n)-->(m) | [(m)-->(x) | x.id]]` returns a list of lists.

You can also bind the matched path to a variable using the syntax `[path = (a)-[r]->(b) | length(path)]`.

### Pattern comprehension in `WHERE` clause

Pattern comprehension can also be combined with comprehension constructs inside the `WHERE` clause.
```cypher
MATCH (n:Person)
WHERE single(x in [(n)-->(m) WHERE m.released > 2000 | m.title] WHERE true)
RETURN actor.name, years, titles;
```

### Storing lists as properties
It is possible to store homogeneous lists of simple values as properties.
For example, the following query creates a list from the title properties of the Movie nodes connected to `Keanu Reeves`.
It then sets that list as a resume property on `Keanu Reeves`.

```cypher
MATCH (keanu:Person {name: 'Keanu Reeves'})
WITH keanu,[(keanu)-->(b:Movie) | b.title] AS movieTitles
SET keanu.resume = movieTitles
RETURN keanu.resume
```

It is not, however, possible to store heterogeneous lists as properties.
For example, the following query, which tries to set a list including both the title and the released properties as the resume property
of `Keanu Reeves` will fail.
This is because the title property values are stored as STRING values, while the released property values are stored as INTEGER values.

```cypher
MATCH (keanu:Person {name: 'Keanu Reeves'})
WITH keanu,[(keanu)-->(b:Movie) | b.title]  + [(keanu)-->(b:Movie) | b.released] AS movieTitles
SET keanu.resume = movieTitles
RETURN keanu.resume
```

## List comprehension

List comprehension is a syntactic construct in Cypher that allows for the
creation of a new list by evaluating an expression over each element of an
existing list, optionally filtering elements based on a predicate. This feature
is particularly useful for transforming and filtering data within queries.

The general syntax for list comprehension in Cypher is:

```cypher
[variable IN list [WHERE predicate] | expression]
```

- **`variable`**: Represents each element in the original list.
- **`list`**: The original list to iterate over.
- **`predicate`** (optional): A condition that filters elements; only elements satisfying this condition are processed.
- **`expression`**: An expression applied to each filtered element; the results form the new list.

When the predicate is `null` for an element, that element is skipped and the
other elements are still returned, the same as when the predicate is `false`.
A list that contains `null`, or a property that an element does not have, does
not turn the whole result into `null`:

```cypher
RETURN [x IN [1, null, 3] WHERE x > 0 | x] AS positives
```

**Result:** `[1, 3]`

If the list itself is `null`, the result is `null`.

**Examples:**

1. **Transforming a list:**

   To create a list of squares from a list of numbers:

```cypher
RETURN [x IN [1, 2, 3, 4] | x * x] AS squares
```

   **Result:** `[1, 4, 9, 16]`

2. **Filtering a list:**

   To filter out even numbers from a list:

```cypher
RETURN [x IN [1, 2, 3, 4] WHERE x % 2 <> 0] AS oddNumbers
```

   **Result:** `[1, 3]`

3. **Combining transformation and filtering:**

   To create a list of squares of even numbers:

```cypher
RETURN [x IN [1, 2, 3, 4] WHERE x % 2 = 0 | x * x] AS evenSquares
```

   **Result:** `[4, 16]`

4. **Extracting node properties:**

   Assuming a graph where `Person` nodes are connected to `Movie` nodes with an `ACTED_IN` relationship, to retrieve the titles of movies released after the year 2000 that a person named 'Alice' acted in:

```cypher
MATCH (alice:Person {name: 'Alice'})-[:ACTED_IN]->(movie:Movie)
RETURN [m IN collect(movie) WHERE m.released > 2000 | m.title] AS recentMovies
```

   **Result:** A list of movie titles released after 2000 that 'Alice' acted in.
