Neo4j 入門 #2 (よく使われる予約語)

# 目的
クエリを書く上でよく使われる6つの予約語を紹介する.
- CREATE
- MERGE
- MATCH
- RETURN
- DELETE
- WHERE

# 前提知識｜グラフデータベースについて
グラフデータベースとは #1 で述べた通りグラフ構造を持ったデータの保存, 探索, 集計に最適化されたデータベースを指す. グラフは 「ノード」, 「エッジ」, 「プロパティ」 の 3 要素によってノードの関係性を表現するものである.

![Untitled Diagram (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287300/286356a9-45ad-1634-12e6-76711131dd24.png)

## ノード(node)
別名バーテックスとも呼ばれる. 頂点. 点や丸で表現されるエンティティ. 「ラベル」を付けて種別を分類することが多い。上図の丸い部分.

## エッジ(edge)
別名リレーションシップとも呼ばれる. 辺. ノード間の関係性を表す. 方向とタイプを有する。上図において Alice ノードから Bob ノードの方向に follows タイプのエッジが存在するが反対方向には存在しない.

## プロパティ（property）
別名、属性。ノードとエッジにおける属性情報。データはkey／value形式で保持される。上図の Alice ノードにおいて Name:Alice, Age:20 のプロパティを保持する

# CREATE文
下記にCREATE文の例を出して説明をする

```
CREATE (n:User{user_id:100, user_name:'Alice'})
```

これはuser_id = 100, user_name = 'Alice'のプロパティをもつノードを作成している．
またUserというのはラベルを示していて, nは識別子を表している.
ラベルとは検索しやすくするために用いるグループ, タグのようなものを表している.
一つのノードに対して複数のタグをつけることもでき，その場合は下記のように記載する.

```
CREATE (:User:Woman:Engineer{user_id:100, user_name:'Alice'})
```

これによりユーザで女性でエンジニアのノードを作ることができる.
<img width="316" alt="スクリーンショット 2019-07-25 11.07.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287300/af64342c-5759-97f4-9334-24221547e94a.png">
識別子は直後に利用したい場合にのみ記載する必要がある.
またリレーションを作成するときは下記のように記載する

```
CREATE (u1:User:Woman:Engineer{user_id:100, user_name:'Alice'})
CREATE (u2:User:Man:SIer{user_id:101, user_name:'Bob'})
CREATE (u1)-[:follows]->(u2)
```

<img width="227" alt="スクリーンショット 2019-07-25 11.09.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287300/87bc4134-9f7a-4a3a-35a9-6a80c2fe97b3.png">

矢印の方向を変えることができるが, 双方向や無向グラフはNeo4jではサポートしていない.
おそらく, 方向を無視するような処理を加えてあげれば良いらしい
またリレーションにプロパティや識別子をノード作成時と同様の記法で書くことができる.

2ホップ以上のグラフも以下のように表される.

# MERGE文
MERGE文は重複を許さないCREATE文である.
すでに同じプロパティをもち, 同じラベルが存在する時は新たにノードを作成しないようにする.

# MATCH文, RETURN文
MATCH文は作成済みのノードを参照するために用いるものである.
ノードを下記のコードで作成する．

```
CREATE (u1:User{user_id:100, user_name:'Alice'})
CREATE (u2:User{user_id:102, user_name:'Bob'})
CREATE (u3:User{user_id:103, user_name:'Carl'})
CREATE (u1)-[:follows]->(u2)-[:follows]->(u3)
```
<img width="217" alt="スクリーンショット 2019-07-25 11.55.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287300/cb2d8eb4-3640-499e-762f-60ae03df44b4.png">

この時全てを参照する場合は下記のように記述する.

```
MATCH (n) 
RETURN n
```

これにより存在する全てのノードおよびリレーションを取ってくることが可能である.
また, 送信元のノードの情報を取ってくる時は下記のように表す.

```
MATCH (n)-[]->() 
RETURN n
```

リレーションのみを参照したい場合は下記のように書く.

```
MATCH ()-[n]->() RETURN n
```

もちろんラベルを通して指定することも可能である.
例えばAliceからBobへのリレーションおよびノードを取得したい場合は

```
MATCH (u1:User{user_name:'Alice'})-[f:follows]->(u2:User{user_name:'Bob'})
RETURN u1, u2, f
```

と書けば良い.
さらに, 間にノードが１つ挟まっているパスの検索は下記のように書くことで実現できる.

```
MATCH (u1:User)--()--(u2:User)
RETURN u1, u2
```
または, 

```
MATCH (u1:User)-[*2]-(u2:User)
RETURN u1, u2
```
とも書ける

# DELETE
これはノードやリレーションシップを消去するためのものである.
RETURN文のように使うと消去ができる.例えば下記のように書いてみる

```
MATCH (u1:User)-[]-(u2:User)
DELETE u1, u2
```

これで一見ノードが消えてくれると思いきやエラー文が出力される

`Neo.ClientError.Schema.ConstraintValidationFailed: Cannot delete node<12>, because it still has relationships. To delete this node, you must first delete its relationships.`

このエラーはリレーションを消去しないでノードを消去しようとすると出力されるものである. リレーションはノードありきのものなのでリレーション単体では存在できない.　故に先にリレーションを消して次にノードを消すという手順を追う必要がある.

```
MATCH (u1:User)-[f:follows]-(u2:User)
DELETE f, u1, u2
```

# WHERE文
WHERE文はSQLのWHERE文のようなものである. 例えば,先ほどのノードのうちuser_idが101番のものを取ってきたいとすると以下のようにクエリを書くことができる.

```
MATCH (n)
WHERE n.user_id = 101
RETURN n
```

これによる結果としてBobのノードを取り出すことができる.
ここで説明したWHERE文はMATCHと一緒に書かないとエラー文がでる.

\#3は[こちら](https://qiita.com/flystaslingan40/items/634ecd72549d4654f4f2)