## 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/)