## CRUD
### Node, Property, Label
#### CREATE
```cypher
CREATE ([Node 이름]:[Label 이름, 복수 가능]{[Property key-value 형식]})
```
- Node는 데이터를 통해 나타낸 실체이다. Label은 그 실체를 포함하는 추상적인 개념이다. Property는 실체가 가지는 데이터다.
- 예를 들어 실제 사람의 이름과 나이 데이터를 저장했다고 하자. 그럼 Node는 각 사람이 되고, Label은 추상적인 '사람'이 되며, Property는 이름과 나이 값이 된다.
##### 예시
```cypher
CREATE (p0:Person:Student {name: "Joe", age: 20})
CREATE (p1:Person:Teacher {name: "Alice", age: 40})
```
![[Pasted image 20240809223858.png]]
#### READ
```cypher
MATCH
([Nodes Alias 1]:[Label 이름]{[Property key-value 형식]}),
([Nodes Alias 2]:[Label 이름]{[Property key-value 형식]}),
...
WHERE
[조건문 1]
...
RETURN
Nodes Alias 1,
...
```
- `MATCH`는 RDBMS의 `FROM`에 대응한다. 다만, 그 방식이 완전히 다른데 테이블을 지정하는 `FROM`과 달리 `MATCH`는 **패턴**을 지정한다.
- `RETURN`은 RDBMS의 `SELECT`에 대응한다. `SELECT`가 열을 지정하는 것처럼 `RETURN`은 Node이나 Relationship, Property 등을 지정한다.
- `RETURN`하는 대상이 일반 value인 경우 Cypher는 자동으로 해당 value와 다른 대상을 그룹핑한다. [^2]
##### 예시
```cypher
MATCH
(p:Person)
WHERE
p.age > 20
RETURN
p
```
![[Pasted image 20240809231041.png]]
#### UPDATE
```cypher
MATCH
[노드 패턴]
WHERE
[조건문]
[SET | REMOVE] [Node Alias]:[Label 이름]
[SET | REMOVE] [Node Alias].[Property 이름] (= [Propery 값])
...
RETURN
...
```
- `SET`과 `REMOVE`를 이용해서 Node의 Label과 Propery를 수정 가능하다.
##### 예시
```cypher
MATCH (p:Person {name: "Joe"})
SET p.age = 55, p.email = "
[email protected]"
REMOVE p:Student
SET p:Professor
RETURN p
```
![[Pasted image 20240809232500.png]]
#### DELETE
```cypher
MATCH
[노드 패턴]
WHERE
[조건문]
(DETACH) DELETE [Node Alias]
RETURN
...
```
##### 예시
```cypher
MATCH (p:Person {name: "Joe"})
DELETE p
RETURN p
```
- `DETACH`의 경우 모든 Relationship을 먼저 삭제하는 옵션이다.
### Relationship
#### CREATE
```cypher
MATCH
[노드 패턴 1],
[노드 패턴 2]
CREATE
([Alias 1])-[:[Relationship 이름]{[Property]}]->([Alias 2])
```
- Relationship은 두 노드(실체) 간의 Directed edge다. 특징은 Label과 Property를 가진다는 점(1)과 동일한 Relationship을 양방향으로 가질 수 있다는 점(2), 그리고 두 노드 간에 복수의 Directed edge를 허용한다는 점(3)이다.
- 조금 아쉬운 점은 무방향 edge가 없다는 점이다. DAGs pattern 같은 경우는 양방향 edge가 아니라 무방향 edge가 있어야 편한데 아쉽다.
##### 예시
```cypher
MATCH (p0:Person {name: "Joe"}), (p1:Person {name: "Alice"})
CREATE (p0)-[:FRIENDS_WITH]->(p1)
CREATE (p1)-[:FRIENDS_WITH]->(p0)
CREATE (p0)-[:IS_ORDER_THAN]->(p1)
RETURN p0, p1
```
![[Pasted image 20240810001749.png]]
#### READ
```cypher
MATCH
[그래프 패턴]
WHERE
[조건문]
RETURN
[그래프 패턴 속 노드, 관계]
```
- `MATCH`에는 노드 패턴 뿐만 아니라 그래프 패턴도 사용할 수 있다. 그래프 DB의 매우 큰 장점으로 이 그래프 패턴을 통한 조회 속도가 RDBMS보다 월등히 빠르다[^1].
##### 예시
```cypher
CREATE (a:V {name: "A", is_observed:false})
CREATE (b:V {name: "B", is_observed:false})
CREATE (c:V {name: "C", is_observed:true})
CREATE (d:V {name: "D", is_observed:false})
CREATE (a)-[:DEPENDS_ON]->(b)
CREATE (a)-[:DEPENDS_ON]->(c)
CREATE (b)-[:DEPENDS_ON]->(d)
CREATE (c)-[:DEPENDS_ON]->(d)
```
![[Pasted image 20240810003653.png]]
- B와 C는 confounder지만, C의 경우 측정 되었다는 차이가 있다.
```cypher
MATCH (v0:V)-[:DEPENDS_ON]->(v1:V)-[:DEPENDS_ON]->(v2:V)
WHERE v1.is_observed = false
RETURN *
```
![[Pasted image 20240810004456.png]]
- `(v0:V)-[:DEPENDS_ON]->(v1:V)-[:DEPENDS_ON]->(v2:V)` 구조를 이루는 서브 그래프 중에 confounder가 측정 안 된 경우만 출력 되었다.
#### UPDATE
```cypher
MATCH
[그래프 패턴]
WHERE
[조건문]
[SET | REMOVE] [Node|Relationship Alias]:[Label 이름]
[SET | REMOVE] [Node|Relationship Alias].[Property 이름] (= [Propery 값])
...
RETURN
...
```
##### 예시
```cypher
MATCH (p0:Person)-[r:IS_ORDER_THAN]->(p1:Person)
SET r.d = p0.age - p1.age
RETURN *
```
![[Pasted image 20240810012703.png]]
- `IS_ORDER_THAN`의 속성으로 두 person 간의 나이 차이를 추가하였다.
#### DELETE
```cypher
MATCH
[그래프 패턴]
WHERE
[조건문]
DELETE [Relationship Alias]
RETURN ...
```
##### 예시
```cypher
MATCH (p0:Person)-[r:FRIENDS_WITH]->(p1:Person)
WHERE p0.age <> p1.age
DELETE r
RETURN *
```
![[Pasted image 20240810013256.png]]
- 서로 나이가 다른 경우(`<>`) `FRIENDS_WITH` 관계를 삭제하였다.
## 참고하면 좋은 글
- [Neo4j Cypher Cheatsheet](https://neo4j.com/docs/cypher-cheat-sheet/5/neo4j-community/)
[^1]: Neo4j 공식 홈페이지에 있는 [실험 결과](https://neo4j.com/news/how-much-faster-is-a-graph-database-really/)를 확인해보자.
[^2]: [Working with Cypher Data](https://neo4j.com/graphacademy/training-querying-40/04-querying40-working-with-cypher-data/)