Add technical documentation on openCypher
Summary: This is a basic overview of various supported features of openCypher in Memgraph. A lot of the documentation refers to Neo4j manual. This needs to change in the future. Reviewers: buda, dtomicevic, mislav.bradac, florijan Reviewed By: buda Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D439
This commit is contained in:
parent
f069677b39
commit
9c6c0c655b
@ -1,3 +1,352 @@
|
||||
## openCypher Query Language
|
||||
|
||||
Details about openCypher
|
||||
[*openCypher*](http://www.opencypher.org/) is a query language for querying
|
||||
graph databases. It's aim is to be intuitive and easy to learn, while
|
||||
providing a powerful interface for working with graph based data.
|
||||
|
||||
*Memgraph* supports most of the commonly used constructs of the language. This
|
||||
chapter contains the details of features which are implemented. Additionally,
|
||||
not yet supported features of the language are listed.
|
||||
|
||||
* [Reading existing Data](#reading-existing-data)
|
||||
* [Writing new Data](#writing-new-data)
|
||||
* [Reading & Writing](#reading-amp-writing)
|
||||
* [Other Features](#other-features)
|
||||
|
||||
### Reading existing Data
|
||||
|
||||
The simplest usage of the language is to find some data stored in the
|
||||
database. For that purpose, the following clauses are offered:
|
||||
|
||||
* `MATCH`, which searches for patterns;
|
||||
* `WHERE`, for filtering the matched data and
|
||||
* `RETURN`, which is used to define the results.
|
||||
|
||||
#### MATCH
|
||||
|
||||
This clause is used to obtain data from Memgraph by matching it to a given
|
||||
pattern. For example, to find each node in the database, you can use the
|
||||
following query.
|
||||
|
||||
MATCH (node) RETURN node
|
||||
|
||||
Finding connected nodes can be achieved by using this query.
|
||||
|
||||
MATCH (node1) -[connection]- (node2) RETURN node1, connection, node2
|
||||
|
||||
In addition to general pattern matching, you can narrow down the search by
|
||||
specifying node labels and properties. Similarly, edge types and properties
|
||||
can also be specified. For example, finding each node labeled as `Person` and
|
||||
with property `age` being 42, is done with this query.
|
||||
|
||||
MATCH (n :Person {age: 42}) RETURN n.
|
||||
|
||||
While their friends can be found with the following.
|
||||
|
||||
MATCH (n :Person {age: 42}) -[:FRIENDS]- (friend) RETURN friend.
|
||||
|
||||
More details on how `MATCH` works can be found
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/clauses/match/).
|
||||
Note that *variable paths* and *named paths* are not yet supported.
|
||||
|
||||
The `MATCH` clause can be modified by prepending the `OPTIONAL` keyword. This
|
||||
`OPTIONAL MATCH` clause behaves the same as a regular `MATCH`, but when it
|
||||
fails to find the pattern, missing parts of the pattern will be filled with
|
||||
`null` values. Examples can be found
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/clauses/optional-match/).
|
||||
|
||||
#### WHERE
|
||||
|
||||
You have already seen that simple filtering can be achieved by using labels
|
||||
and properties in `MATCH` patterns. When more complex filtering is desired,
|
||||
you can use `WHERE` paired with `MATCH` or `OPTIONAL MATCH`. For example,
|
||||
finding each person older than 20 is done with the this query.
|
||||
|
||||
MATCH (n :Person) WHERE n.age > 20 RETURN n
|
||||
|
||||
Additional examples are over
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/clauses/where/).
|
||||
|
||||
#### RETURN
|
||||
|
||||
The `RETURN` clause is used to define which data should be included in the
|
||||
resulting set. The simplest usage was already shown in the examples for
|
||||
`MATCH` and `WHERE` clauses. Another simple feature of `RETURN` is renaming
|
||||
the results via the `AS` keyword.
|
||||
|
||||
Example.
|
||||
|
||||
MATCH (n :Person) RETURN n AS people
|
||||
|
||||
That query would but all nodes under the column named `people` instead of `n`.
|
||||
|
||||
When you want to get everything that was matched, you can use the `*` symbol
|
||||
as a shortcut.
|
||||
|
||||
This query:
|
||||
|
||||
MATCH (node1) -[connection]- (node2) RETURN *
|
||||
|
||||
is equivalent to:
|
||||
|
||||
MATCH (node1) -[connection]- (node2) RETURN node1, connection, node2
|
||||
|
||||
`RETURN` can be followed with the `DISTINCT` operator, which will remove
|
||||
duplicate results. For example, getting unique names of people is done with:
|
||||
|
||||
MATCH (n :Person) RETURN DISTINCT n.name
|
||||
|
||||
Besides choosing what will be the result and how it will be named, `RETURN`
|
||||
clause can also be used to:
|
||||
|
||||
* limit or skip results with `LIMIT` or `SKIP` sub-clauses respectively;
|
||||
* order results with `ORDER BY` sub-clause and
|
||||
* perform aggregations.
|
||||
|
||||
More details on `RETURN` itself can be found
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/clauses/return/).
|
||||
|
||||
##### SKIP & LIMIT
|
||||
|
||||
These simple sub-clauses take the number of how many results to skip or limit.
|
||||
For example, to get the first 3 results you can use this query.
|
||||
|
||||
MATCH (n :Person) RETURN n LIMIT 3
|
||||
|
||||
If you want to get all the results after the first 3, you can use the
|
||||
following.
|
||||
|
||||
MATCH (n :Person) RETURN n SKIP 3
|
||||
|
||||
The `SKIP` and `LIMIT` can be combined. So for example, to get the 2nd result,
|
||||
you can do:
|
||||
|
||||
MATCH (n :Person) RETURN n SKIP 1 LIMIT 1
|
||||
|
||||
##### ORDER BY
|
||||
|
||||
Since the patterns which are matched can come in any order, it is very useful
|
||||
to be able to enforce some ordering among the results. In such cases, you can
|
||||
use the `ORDER BY` sub-clause.
|
||||
|
||||
For example, the following query will get all people and order them by their
|
||||
names.
|
||||
|
||||
MATCH (n :Person) RETURN n ORDER BY n.name
|
||||
|
||||
By default, results will be in the ascending order. To change the order to be
|
||||
descending, you should append `DESC`.
|
||||
|
||||
For example, to order people by their name descending, you can use this query.
|
||||
|
||||
MATCH (n :Person) RETURN n ORDER BY n.name DESC
|
||||
|
||||
You can also order by multiple variables. The results will be sorted by the
|
||||
first variable listed. If the values are equal, the results are sorted by the
|
||||
second variable, and so on.
|
||||
|
||||
Example. Ordering by first name descending and last name ascending.
|
||||
|
||||
MATCH (n :Person) RETURN n ORDER BY n.name DESC, n.lastName
|
||||
|
||||
The `ORDER BY` sub-clause may come in handy with `SKIP` and/or `LIMIT`
|
||||
sub-clauses. For example, to get the oldest person you can use the following.
|
||||
|
||||
MATCH (n :Person) RETURN n ORDER BY n.age DESC LIMIT 1
|
||||
|
||||
##### Aggregating
|
||||
|
||||
openCypher has functions for aggregating the data. Memgraph currently supports
|
||||
the following aggregate functions.
|
||||
|
||||
* `avg`, for calculating the average.
|
||||
* `collect`, for collecting multiple values into a single list.
|
||||
* `count`, for counting the resulting values.
|
||||
* `max` and `min`, for calculating the maximum and minimum result,
|
||||
respectively.
|
||||
* `sum`, for getting the sum of numeric results.
|
||||
|
||||
Example, calculating the average age.
|
||||
|
||||
MATCH (n :Person) RETURN avg(n.age) AS averageAge
|
||||
|
||||
Click
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/functions/aggregating/)
|
||||
for additional details on how aggregations work.
|
||||
|
||||
### Writing new Data
|
||||
|
||||
For adding new data, you can use the following clauses.
|
||||
|
||||
* `CREATE`, for creating nodes and edges.
|
||||
* `SET`, for creating or updating labels, properties and edge types.
|
||||
* `DELETE`, for deleting nodes and edge.
|
||||
* `REMOVE`, for removing labels and properties.
|
||||
|
||||
You can still use the `RETURN` clause to produce results after creation, but
|
||||
it is not mandatory.
|
||||
|
||||
#### CREATE
|
||||
|
||||
This clause is used to add new nodes and edges to the database. The creation
|
||||
is done by providing a pattern, similarly to `MATCH` clause.
|
||||
|
||||
For example, to create 2 new nodes connected with a new edge, use this query.
|
||||
|
||||
CREATE (node1) -[:edge_type]-> (node2)
|
||||
|
||||
Additional information on `CREATE` is
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/clauses/create/).
|
||||
|
||||
#### SET
|
||||
|
||||
The `SET` clause is used to update labels and properties of already existing
|
||||
data.
|
||||
|
||||
Example. Incrementing everyone's age by 1.
|
||||
|
||||
MATCH (n :Person) SET n.age = n.age + 1
|
||||
|
||||
Click
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/clauses/create/)
|
||||
for a more detailed explanation on what can be done with `SET`.
|
||||
|
||||
#### DELETE
|
||||
|
||||
This clause is used to delete nodes and edges from the database.
|
||||
|
||||
Example. Removing all edges of a single type.
|
||||
|
||||
MATCH () -[edge :type]- () DELETE edge
|
||||
|
||||
When testing the database, you want to often have a clean start by deleting
|
||||
every node and edge in the database. It is reasonable that deleting each node
|
||||
should delete all edges coming into or out of that node.
|
||||
|
||||
MATCH (node) DELETE node
|
||||
|
||||
But, openCypher prevents accidental deletion of edges. Therefore, the above
|
||||
query will report an error. Instead, you need to use the `DETACH` keyword,
|
||||
which will remove edges from a node you are deleting. The following should
|
||||
work and *delete everything* in the database.
|
||||
|
||||
MATCH (node) DETACH DELETE node
|
||||
|
||||
More examples are
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/clauses/delete/).
|
||||
|
||||
#### REMOVE
|
||||
|
||||
The `REMOVE` clause is used to remove labels and properties from nodes and
|
||||
edges.
|
||||
|
||||
Example.
|
||||
|
||||
MATCH (n :WrongLabel) REMOVE n :WrongLabel, n.property
|
||||
|
||||
### Reading & Writing
|
||||
|
||||
The query language supports combining multiple reads and writes using the
|
||||
`WITH` clause. In addition to combining, the `MERGE` clause is provided which
|
||||
may create patterns if they do not exist.
|
||||
|
||||
#### WITH
|
||||
|
||||
The write part of the query cannot be simply followed by another read part. In
|
||||
order to combine them, `WITH` clause must be used. The names this clause
|
||||
establishes are transferred from one part to another.
|
||||
|
||||
For example, creating a node and finding all nodes with the same property.
|
||||
|
||||
CREATE (node {property: 42}) WITH node.property AS propValue
|
||||
MATCH (n {property: propValue}) RETURN n
|
||||
|
||||
Note that the `node` is not visible after `WITH`, since only `node.property`
|
||||
was carried over.
|
||||
|
||||
This clause behaves very much like `RETURN`, so you should refer to features
|
||||
of `RETURN`.
|
||||
|
||||
#### MERGE
|
||||
|
||||
The `MERGE` clause is used to ensure that a pattern you are looking for exists
|
||||
in the database. This means that if the pattern is not found, it will be
|
||||
created. In a way, this clause is like a combination of `MATCH` and `CREATE`.
|
||||
|
||||
|
||||
Example. Ensure that a person has at least one friend.
|
||||
|
||||
MATCH (n :Person) MERGE (n) -[:FRIENDS]-> (m)
|
||||
|
||||
The clause also provides additional features for updating the values depending
|
||||
on whether the pattern was created or matched. This is achieved with `ON
|
||||
CREATE` and `ON MATCH` sub clauses.
|
||||
|
||||
Example. Set a different properties depending on what `MERGE` did.
|
||||
|
||||
MATCH (n :Person) MERGE (n) -[:FRIENDS]-> (m)
|
||||
ON CREATE SET m.prop = "created" ON MATCH SET m.prop = "existed"
|
||||
|
||||
For more details, click [this
|
||||
link](https://neo4j.com/docs/developer-manual/current/cypher/clauses/merge/).
|
||||
|
||||
|
||||
### Other Features
|
||||
|
||||
The following sections describe some of the other supported features.
|
||||
|
||||
#### UNWIND
|
||||
|
||||
The `UNWIND` clause is used to unwind a list of values as individual rows.
|
||||
|
||||
Example. Produce rows out of a single list.
|
||||
|
||||
UNWIND [1,2,3] AS listElement RETURN listElement
|
||||
|
||||
More examples are
|
||||
[here](https://neo4j.com/docs/developer-manual/current/cypher/clauses/unwind/).
|
||||
|
||||
#### Functions
|
||||
|
||||
You have already been introduced to one type of functions, [aggregating
|
||||
functions](#aggregating). This section contains the list of other supported
|
||||
functions.
|
||||
|
||||
Name | Description
|
||||
--------------|------------
|
||||
`coalesce` | Returns the first non null argument.
|
||||
`startNode` | Returns the starting node of an edge.
|
||||
`endNode` | Returns the destination node of an edge.
|
||||
`head` | Returns the first element of a list.
|
||||
`last` | Returns the last element of a list.
|
||||
`properties` | Returns the properties of a node or an edge.
|
||||
`size` | Returns the number of elements in a list.
|
||||
`toBoolean` | Converts the argument to a boolean.
|
||||
`toFloat` | Converts the argument to a floating point number.
|
||||
`toInteger` | Converts the argument to an integer.
|
||||
`type` | Returns the type of an edge as a character string.
|
||||
`keys` | Returns a list keys of properties from an edge or a node. Each key is represented as a string of characters.
|
||||
`labels` | Return a list of labels from a node. Each label is represented as a character string.
|
||||
`range` | Constructs a list of value in given range.
|
||||
`tail` | Returns all elements after the first of a given list.
|
||||
`abs` | Returns the absolute value of a number.
|
||||
`ceil` | Returns the smallest integer greater than or equal to given number.
|
||||
`floor` | Returns the largest integer smaller than or equal to given number.
|
||||
`round` | Returns the number, rounded to the nearest integer. Tie-breaking is done using the *commercial rounding*, where -1.5 produces -2 and 1.5 produces 2.
|
||||
`exp` | Calculates `e^n` where `e` is the base of the natural logarithm, and `n` is the given number.
|
||||
`log` | Calculates the natural logarithm of a given number.
|
||||
`log10` | Calculates the logarithm (base 10) of a given number.
|
||||
`sqrt` | Calculates the square root of a given number.
|
||||
`acos` | Calculates the arccosine of a given number.
|
||||
`asin` | Calculates the arcsine of a given number.
|
||||
`atan` | Calculates the arctangent of a given number.
|
||||
`atan2` | Calculates the arctangent2 of a given number.
|
||||
`cos` | Calculates the cosine of a given number.
|
||||
`sin` | Calculates the sine of a given number.
|
||||
`tan` | Calculates the tangent of a given number.
|
||||
`sign` | Applies the signum function to a given number and returns the result. The signum of positive numbers is 1, of negative -1 and for 0 returns 0.
|
||||
`e` | Returns the base of the natural logarithm.
|
||||
`pi` | Returns the constant *pi*.
|
||||
`startsWith` | Check if the first argument starts with the second.
|
||||
`endsWith` | Check if the first argument ends with the second.
|
||||
`contains` | Check if the first argument has an element which is equal to the second argument.
|
||||
|
Loading…
Reference in New Issue
Block a user