summaryrefslogtreecommitdiffhomepage
path: root/cypher.html.markdown
blob: 2b8e9ac807b742d45692c57f9a6d7672ccef7df7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
---
language: cypher
filename: LearnCypher.cql
contributors:
    - ["Théo Gauchoux", "https://github.com/TheoGauchoux"]
---

Cypher is the Neo4j’s query language to manipulate graphs easily. It reuses syntax from SQL and mixes it with kind of ascii-art to represent graphs.
This tutorial assumes that you already know graph concepts like nodes and relationships.

[Read more here.](https://neo4j.com/developer/cypher-query-language/)


Nodes
---

**Represents a record in a graph.**

```()```
It's an empty *node*, to indicate that there is a *node*, but it's not relevant for the query.

```(n)```
It's a *node* refered by the variable **n**, reusable in the query. It begins with lowercase and uses camelCase.

```(p:Person)```
You can add a *label* to your node, here **Person**. It's like a type / a class / a category. It begins with uppercase and uses camelCase.

```(p:Person:Manager)```
A node can have many *labels*.

```(p:Person {name : 'Théo Gauchoux', age : 22})```
A node can have some *properties*, here **name** and **age**. It begins with lowercase and uses camelCase.

The types allowed in properties :

 - Numeric
 - Boolean
 - String
 - List of previous primitive types

*Warning : there isn't datetime property in Cypher ! You can use String with a specific pattern or a Numeric from a specific date.*

```p.name```
You can access to a property with the dot style.


Relationships (or Edges)
---

**Connects two nodes**

```[:KNOWS]```
It's a *relationship* with the *label* **KNOWS**. It's a *label* as the node's label. It begins with uppercase and use UPPER_SNAKE_CASE.

```[k:KNOWS]```
The same *relationship*, refered by the variable **k**, reusable in the query, but it's not necessary.

```[k:KNOWS {since:2017}]```
The same *relationship*, with *properties* (like *node*), here **since**.

```[k:KNOWS*..4]```
It's a structural information to use in a *path* (seen later). Here, **\*..4** says "Match the pattern, with the relationship **k** which be repeated between 1 and 4 times.


Paths
---

**The way to mix nodes and relationships.**

```(a:Person)-[:KNOWS]-[b:Person]```
A path describing that **a** and **b** know each other.

```(a:Person)-[:MANAGES]->[b:Person]```
A path can be directed. This path describes that **a** is the manager of **b**.

```(a:Person)-[:KNOWS]-[b:Person]-[:KNOWS]-[c:Person]```
You can chain multiple relationships. This path describes the friend of a friend.

```(a:Person)-[:MANAGES]->[b:Person]-[:MANAGES]->[c:Person]```
A chain can also be directed. This path describes that **a** is the boss of **b** and the big boss of **c**.

Patterns often used (from Neo4j doc) :

```
// Friend-of-a-friend 
(user)-[:KNOWS]-(friend)-[:KNOWS]-(foaf)

// Shortest path
path = shortestPath( (user)-[:KNOWS*..5]-(other) )

// Collaborative filtering
(user)-[:PURCHASED]->(product)<-[:PURCHASED]-()-[:PURCHASED]->(otherProduct)

// Tree navigation 
(root)<-[:PARENT*]-(leaf:Category)-[:ITEM]->(data:Product)

```


Create queries
---

Create a new node
```
CREATE (a:Person {name:"Théo Gauchoux"})
RETURN a
```
*`RETURN` allows to have a result after the query. It can be multiple, as `RETURN a, b`.*

Create a new relationship (with 2 new nodes)
```
CREATE (a:Person)-[k:KNOWS]-(b:Person)
RETURN a,k,b
```

Match queries
---

Match all nodes
```
MATCH (n)
RETURN n
```

Match nodes by label
```
MATCH (a:Person)
RETURN a
```

Match nodes by label and property
```
MATCH (a:Person {name:"Théo Gauchoux"})
RETURN a
```

Match nodes according to relationships (undirected)
```
MATCH (a)-[:KNOWS]-(b)
RETURN a,b
```

Match nodes according to relationships (directed)
```
MATCH (a)-[:MANAGES]->(b)
RETURN a,b
```

Match nodes with a `WHERE` clause
```
MATCH (p:Person {name:"Théo Gauchoux"})-[s:LIVES_IN]->(city:City)
WHERE s.since = 2015
RETURN p,state
```

You can use `MATCH WHERE` clause with `CREATE` clause
```
MATCH (a), (b)
WHERE a.name = "Jacquie" AND b.name = "Michel"
CREATE (a)-[:KNOWS]-(b)
```


Update queries
---

Update a specific property of a node
```
MATCH (p:Person)
WHERE p.name = "Théo Gauchoux"
SET p.age = 23
```

Replace all properties of a node
```
MATCH (p:Person)
WHERE p.name = "Théo Gauchoux"
SET p = {name: "Michel", age: 23}
```

Add new property to a node
```
MATCH (p:Person)
WHERE p.name = "Théo Gauchoux"
SET p + = {studies: "IT Engineering"}
```

Add a label to a node
```
MATCH (p:Person)
WHERE p.name = "Théo Gauchoux"
SET p:Internship
```


Delete queries
---

Delete a specific node (linked relationships must be deleted before)
```
MATCH (p:Person)-[relationship]-()
WHERE p.name = "Théo Gauchoux"
DELETE relationship, p
```

Remove a property in a specific node
```
MATCH (p:Person)
WHERE p.name = "Théo Gauchoux"
REMOVE p.age
```
*Pay attention to the `REMOVE`keyword, it's not `DELETE` !*

Remove a label from a specific node
```
MATCH (p:Person)
WHERE p.name = "Théo Gauchoux"
DELETE p:Person
```

Delete entire database
```
MATCH (n)
OPTIONAL MATCH (n)-[r]-()
DELETE n, r
```
*Seriously, it's the `rm -rf /` of Cypher !*


Other useful clauses
---

```PROFILE```
Before a query, show the execution plan of it.

```COUNT(e)```
Count entities (nodes or relationships) matching **e**.

```LIMIT x```
Limit the result to the x first results.


Special hints
---

- There is just single-line comments in Cypher, with double-slash : // Comments
- You can execute a Cypher script stored in a **.cql** file directly in Neo4j (it's an import). However, you can't have multiple statements in this file (separed by **;**).
- Use the Neo4j shell to write Cypher, it's really awesome.
- The Cypher will be the standard query language for all graph databases (known as **OpenCypher**).