Neo4j - Installing on Windows 7

# 概要

Neo4jはJavaで開発されているグラフ型データベースです。
Windows 7に開発・検証目的用にNeo4j Community Editionをインストールし、初歩的な操作を行うまでの作業メモです。
インストールにはZIP Archiveを使用します。

**環境**

下記の環境で動作確認を行いました。

* Windows7 (64bit)
* Java 1.7.0_79
* Neo4j Community Edition 2.2.3

**参考**

下記のサイトを参考にさせて頂きました。

Neo4j

* [The Neo4j Manual v2.2.3] (http://neo4j.com/docs/stable/preface.html)
* [Neo4j Cypher Refcard 2.2.3] (http://neo4j.com/docs/stable/cypher-refcard/)

Qiita

* [WindowsでNeo4jを使ってみる] (http://qiita.com/awk256/items/5622d601c2c3051b70ad)

その他

* [グラフ構造のデータを高速検索するグラフ型データベース「Neo4j」の勘所 - ZDNet Japan] (http://japan.zdnet.com/article/35063431/)
* [グラフデータベースはどんな用途に向いている？ - @IT] (http://www.atmarkit.co.jp/ait/articles/1507/28/news015.html)

## インストール

[Neo4j] (http://neo4j.com/)よりインストール用のアーカイブファイルをダウンロードします。

* ページ右上のメニューの"Download Neo4j" -> Communityの"Other Releases"をクリック
* Community版のWindows 64bitの"Neo4j 2.2.3(zip)"をクリック
* Thanks for downloading Neo4jページに遷移し暫く待つとダウンロードが始まります。

今回ダウンロードしたアーカイブファイルは"neo4j-community-2.2.3-windows.zip"です。
ダウンロードしたアーカイブファイルを任意の場所（この記事では"D:\dev\neo4j-community-2.2.3"へ展開しました）へ展開します。
次に環境変数"NEO4J_HOME"へこのディレクトリを登録します。

また、Neo4jの起動にはJava7が必要です。
下記はjava8で起動したときのエラーメッセージです。（メッセージは表示されますが起動するようです。）

```text:java8
D:\dev\neo4j-community-2.2.3>bin\Neo4j.bat
ERROR! You are using an unsupported version of Java, please use Oracle HotSpot 1.7.
```

(追記)CHANGES.txtに下記の記述がありました。Version 2.2.2よりJava8をサポートしていました。

```text:CHANGES.txt
General:
o Added support for Java 8
```

### ディレクトリ構成

展開直後のディレクトリ、ファイルの構成です。
binディレクトリにNeo4jサーバーの起動バッチファイルがあります。

```text:Tree
$NEO4J_HOME
│
├─bin
│      base.bat
│      functions.bat
│      Neo4j.bat
│      Neo4jImport.bat
│      Neo4jInstaller.bat
│      Neo4jShell.bat
│      README.txt
│      windows-service-wrapper-5.jar
│
├─conf
│  │  custom-logback.xml
│  │  logging.properties
│  │  neo4j-http-logging.xml
│  │  neo4j-server.properties
│  │  neo4j-wrapper.conf
│  │  neo4j.properties
│  │  README.txt
│  │  windows-wrapper-logging.properties
│  │
│  └─ssl
│          snakeoil.cert
│          snakeoil.key
│
├─data
│  │  README.txt
│  │
│  └─log
│          README.txt
│
├─lib
│      ...省略...
│
├─plugins
│      README.txt
│
└─system
    │  README.txt
    │
    └─lib
            ...省略...
```

## サーバー起動

Java8が環境変数JAVA_HOMEに設定済みの場合は、下記のように一時的にJava7を設定します。

```bat:JAVA_HOME
> set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_79
```

コマンドプロンプトを開き、カレントディレクトリを$NEO4J_HOMEに変えます。
下記のようにneo4j.batを実行するとスタートアップが始まり、コマンドプロンプトとは別にJavaプロセスのウィンドウが開きます。

```bat:startup
D:\dev\neo4j-community-2.2.3>bin\neo4j.bat
2015-07-30 12:28:32.865+0000 INFO  [API] Setting startup timeout to: 120000ms based on 120000
2015-07-30 12:28:35.471+0000 INFO  [API] Successfully started database
2015-07-30 12:28:35.508+0000 INFO  [API] Starting HTTP on port :7474 with 8 threads available
2015-07-30 12:28:35.687+0000 INFO  [API] Enabling HTTPS on port :7473

... 省略...

2015-07-30 12:28:37.215+0000 INFO  [API] Server started on: http://localhost:7474/
2015-07-30 12:28:37.215+0000 INFO  [API] Remote interface ready and available at [http://localhost:7474/]
```

### Web Interface

Neo4jにはブラウザベースのUIが用意されていて、サーバーを起動すると同時に使用できます。

[Web Interface] (http://neo4j.com/docs/stable/tools-webadmin.html)

#### browser

Cypher Query Languageを実行してノードやリレーションを視覚的に確認したり、サーバーの情報を取得することができます。
Browser UIを使用するには下記のURLにアクセスします。

http://localhost:7474/

最初にアクセスするとログインページが表示されます。
デフォルトのユーザーを使ってログインします。（ユーザー名／パスワードは"neo4j/neo4j"です）

![FireShot Capture - Neo4j - http___localhost_7474_browser_.png](https://qiita-image-store.s3.amazonaws.com/0/22772/9cf67420-d864-6363-e9a2-55a8c61b5c63.png)

neo4jユーザーのパスワードを変更します。

![FireShot Capture - Neo4j - http___localhost_7474_browser_2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/c173ffed-df4b-70cd-4b9d-b6bdd6d3c8cd.png)

下図はMovieチュートリアルのデータを取り込んだ後の状態です。

![FireShot Capture - Neo4j D__dev_NEO4J-~1.3_data_graph.db - http___localhost_7474_browser_.png](https://qiita-image-store.s3.amazonaws.com/0/22772/12da0fdd-6921-c8e9-84bc-d8239ea2cd75.png)

例えば、左側のメニューの"Relationship types"から'PRODUCED'をクリックすると、そのリレーションと関係するノードを視覚的に確認することができます。

![FireShot Capture - Neo4j D__dev_NEO4J-~1.3_data_graph.db - http___localhost_7474_browser_2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/f5ac0616-a953-cb3f-3bf3-431c33780f8e.png)

実行計画の可視化

```text
MATCH (m:Movie)<-[ACTED_IN]-(p:Person)
WHERE p.name = "Tom Hanks"
WITH m, p
MATCH (m)<-[:DIRECTED]-(d:Person)
RETURN *;
```

上記のクエリの結果を可視化することができます。

![tom_hanks.png](https://qiita-image-store.s3.amazonaws.com/0/22772/ec11972f-1099-d72e-9bdf-e7d41b2e7354.png)

また、クエリの先頭にexplain句をつけると実行計画も可視化することができます。

![explain.png](https://qiita-image-store.s3.amazonaws.com/0/22772/c260d1cb-f48b-7580-66b4-f409767ad44e.png)


#### webadmin

管理者用の機能を備えたページです。"Data browser"や"consoel"からノードやリレーションを参照したり、更新、削除を行うことができます。
Webadmin UIを使用するには下記のURLにアクセスします。

http://localhost:7474/webadmin/

![FireShot Capture - Neo4j - 2.2.3 - http___localhost_7474_webadmin_#.png](https://qiita-image-store.s3.amazonaws.com/0/22772/a832c69d-76a8-163a-0e6e-482a59aa6461.png)


### サーバー停止

サーバーを停めるときは、Javaプロセスのウィンドウをアクティブにした状態でCtrl + Cキーを押します。


## Neo4jShell

Neo4jShell.batというコマンドラインツールがあります。
このコマンドラインツールを使用してデータを登録したり検索を行うことができます。

[Neo4j Shell] (http://neo4j.com/docs/stable/shell.html)

### Shellの起動

```bat:shell
D:\dev\neo4j-community-2.2.3>bin\Neo4jShell.bat
Welcome to the Neo4j Shell! Enter 'help' for a list of commands
NOTE: Remote Neo4j graph database service 'shell' at port 1337

neo4j-sh (?)$
```

クエリの例

```text:query
$ MATCH (m)<--(c) WHERE m.title = "The Castle of Sand" RETURN m.title, m.released, c.name;
+-----------------------------------------------------+
| m.title              | m.released | c.name          |
+-----------------------------------------------------+
| "The Castle of Sand" | 1974       | "Tetsuro Tanba" |
+-----------------------------------------------------+
1 row
42 ms
```

### Shell Options

**host,port**

hostとportを使用してリモート接続します。
(接続先のNeo4jサーバーが起動している必要があります。)

```bat
D:\dev\neo4j-community-2.2.3>bin\Neo4jShell.bat -host localhost -port 1337
Welcome to the Neo4j Shell! Enter 'help' for a list of commands
NOTE: Remote Neo4j graph database service 'shell' at port 1337

neo4j-sh (?)$
```

**path**

指定するdbを使用してローカル接続します。
(接続先のNeo4jサーバーが起動していると接続できません。)

```bat
D:\dev\neo4j-community-2.2.3>bin\Neo4jShell.bat -path data/graph.db
NOTE: Local Neo4j graph database service at 'data\graph.db'
Welcome to the Neo4j Shell! Enter 'help' for a list of commands

neo4j-sh (?)$
```

**readonly**

読み取り専用で起動します。

```bat
D:\dev\neo4j-community-2.2.3>bin\Neo4jShell.bat -readonly
```

**config**

指定するconfigファイルを使用して起動します。

```bat
D:\dev\neo4j-community-2.2.3>bin\Neo4jShell.bat -config conf/neo4j.properties
```

## Neo4jの基礎

[The Neo4j Graph Database] (http://neo4j.com/docs/stable/graphdb-neo4j.html)

### データ構造

**Nodes**

プロパティを定義することでデータベースのレコードのように扱うことができます。
ノードは複数のラベルをつけることができます。

> A graph records data in nodes and relationships.
> Both can have properties.
> This is sometimes referred to as the Property Graph Model.

**Relationships**

開始ノードと終了ノードの関係を定義します。複数のプロパティを定義することできます。
リレーションシップにはタイプをつけることができます。

> Relationships organize the nodes by connecting them.
> A relationship connects two nodes — a start node and an end node. Just like nodes, relationships can have properties.

**Properties**

ノードやリレーションシップの属性(key-valueの形)です。

> Both nodes and relationships can have properties.
> Properties are named values where the name is a string. The supported property values are:

* Numeric values
* String values
* Boolean values
* Collections of any other type of value

**Labels**

ノードのタイプや役割です。

> Labels assign roles or types to nodes.

**Paths**

> A path is one or more nodes with connecting relationships, typically retrieved as a query or traversal result.


### Cypher Query Language

Cypherはグラフ型データベースのデータを操作するための問い合わせ言語です。

**Cypherでは**

* `()`は、ノードを表します。
* `{key:value}`は、プロパティを表します。
* `<--`,`-->`,`--`は、リレーションシップを表します。

この命令は次のような意味になります。

```text:create
CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})
```

* `CREATE (TheMatrix:Movie {...})` : Movieというラベルを持つノードを作成し、TheMatirixという識別子で参照できるようにする。
* `{title:'The Matrix', released:1999, tagline:'Welcome to the Real World'}` : ノードにtitle,released,taglineというプロパティを定義する。

**Node Syntax**

|Syntax                                                     |description |
|:----------------------------------------------------------|:----------------------------------------------|
|`()`                                                       |ノード                                         |
|`(matrix)`                                                 |ノードを識別子matrixで参照する                 |
|`(:Movie)`                                                 |ラベルMovieを持つノード                        |
|`(matrix:Movie)`                                           |ラベルMovieを持つノードを識別子matrixで参照する|
|`(matrix:Movie {title: "The Matrix"})`                     |ラベルMovieを持ちtitleプロパティが"The Matrix"であるノードを識別子matrixで参照する|
|`(matrix:Movie {title: "The Matrix", released: 1997})`     |ラベルMovieを持ちtitleプロパティが"The Matrix",releasedプロパティが1997であるノードを識別子matrixで参照する|

**Relationship Syntax**

|Syntax                                                     |description |
|:----------------------------------------------------------|:----------------------------------------------|
|`-->`                                                      |リレーション                                   |
|`-[role]->`                                                |リレーションを識別子roleで参照する             |
|`-[:ACTED_IN]->`                                           |タイプACTED_INを持つリレーション               |
|`-[role:ACTED_IN]->`                                       |タイプACTED_INを持つリレーションを識別子roleで参照する|
|`-[role:ACTED_IN {roles: ["Neo"]}]->`                      |タイプACTED_INを持ちrolesプロパティが"Neo"であるリレーションを識別子roleで参照する|


#### 問い合わせの例

**その1**

```text
$ MATCH (m:Movie) RETURN m;
+--------------------------------------------------------------------------------------------------------------+
| m                                                                                                            |
+--------------------------------------------------------------------------------------------------------------+
| Node[52]{title:"The Matrix",released:1999,tagline:"Welcome to the Real World"}                               |
| Node[61]{title:"The Matrix Reloaded",released:2003,tagline:"Free your mind"}                                 |
| Node[62]{title:"The Matrix Revolutions",released:2003,tagline:"Everything that has a beginning has an end"}  |
| Node[63]{title:"The Devil's Advocate",released:1997,tagline:"Evil has its winning ways"}                     |
...省略...
40 rows
203 ms
```

* Movieというラベルを持つノードを検索します。
* そのノードを識別子mで参照できるようにします。
* 識別子mで参照するノードの値を返します。

```text
$ MATCH (m1:Movie {title:'The Matrix'}), (m2:Movie {title:'The Matrix Reloaded'}) RETURN m1.tagline, m2.tagline;
+------------------------------------------------+
| m1.tagline                  | m2.tagline       |
+------------------------------------------------+
| "Welcome to the Real World" | "Free your mind" |
+------------------------------------------------+
1 row
69 ms
```
* カンマで区切ることで複数のノードを指定することができます。

**その2**

```text
$ MATCH (m {title:'The Matrix'}) RETURN m.title, m.released;
+---------------------------+
| m.title      | m.released |
+---------------------------+
| "The Matrix" | 1999       |
+---------------------------+
1 row
41 ms
```

* titleプロパティが'The Matrix'であるノードを検索します。
* そのノードを識別子mで参照できるようにします。
* 識別子mで参照するノードのtitle、releasedプロパティの値を返します。

**その3**

```text
$ MATCH (m {title:'The Matrix'}) RETURN m.id, m.title, m.released;
+------------------------------------+
| m.id   | m.title      | m.released |
+------------------------------------+
| <null> | "The Matrix" | 1999       |
+------------------------------------+
1 row
75 ms
```

* 存在しないプロパティを取得しようとした場合、nullが返ります。
* このクエリではノードのIDも取得したいのですが、プロパティにIDは存在しないのでnullになります。

```text
$ MATCH (m {title:'The Matrix'}) RETURN id(m), m.title, m.released;
+-----------------------------------+
| id(m) | m.title      | m.released |
+-----------------------------------+
| 52    | "The Matrix" | 1999       |
+-----------------------------------+
1 row
44 ms
```

* ノードのIDを取得するにはid()関数を使用します。

**その4**

```text
$ MATCH (m {title:'The Matrix'})<-[r:ACTED_IN]-(c) RETURN m.title, m.released, r.roles, c.name;
+--------------------------------------------------------------------+
| m.title      | m.released | r.roles         | c.name               |
+--------------------------------------------------------------------+
| "The Matrix" | 1999       | ["Emil"]        | "Emil Eifrem"        |
| "The Matrix" | 1999       | ["Trinity"]     | "Carrie-Anne Moss"   |
| "The Matrix" | 1999       | ["Morpheus"]    | "Laurence Fishburne" |
| "The Matrix" | 1999       | ["Agent Smith"] | "Hugo Weaving"       |
| "The Matrix" | 1999       | ["Neo"]         | "Keanu Reeves"       |
+--------------------------------------------------------------------+
5 rows
59 ms
```

* titleプロパティが'The Matrix'であるノードを検索します。
* そのノードを識別子mで参照できるようにします。
* mに対してACTED_INというタイプのリレーションを持つノードを検索します。
* そのノードを識別子cで参照できるようにします。
* また、このリレーションを識別子rで参照できるようにします。
* 識別子mで参照するノードのtitle、releasedプロパティ、識別子cで参照するノードのnameプロパティ、識別子rで参照するリレーションのrolesプロパティの値を返します。

下記は、上記のクエリとはリレーションの向きを変えたものですが、この向きのリレーションを持つノードは無いので結果は返りません。

```text
$ MATCH (m {title:'The Matrix'})-[r:ACTED_IN]->(c) RETURN m.title, m.released, r.roles, c.name;
+-----------------------------------------+
| m.title | m.released | r.roles | c.name |
+-----------------------------------------+
+-----------------------------------------+
0 row
42 ms
```

OPTIONAL MATCHはSQLの外部結合に似た動作をします。
上記のクエリをOPTIONAL MATCHを使用するように修正すると下記の結果が返ります。

```text
$ MATCH (m {title:'The Matrix'}) OPTIONAL MATCH (m)-[r]->(c) RETURN m.title, m.released, r.roles, c.name;
+----------------------------------------------+
| m.title      | m.released | r.roles | c.name |
+----------------------------------------------+
| "The Matrix" | 1999       | <null>  | <null> |
+----------------------------------------------+
1 row
20 ms
```

リレーションの向きを考慮したくない場合は、下記のようにリレーションを`-[ ... ]-`で表現します。

```text
$ MATCH (m {title:'The Matrix'})-[r:ACTED_IN]-(c) RETURN m.title, m.released, r.roles, c.name;
+--------------------------------------------------------------------+
| m.title      | m.released | r.roles         | c.name               |
+--------------------------------------------------------------------+
| "The Matrix" | 1999       | ["Emil"]        | "Emil Eifrem"        |
| "The Matrix" | 1999       | ["Trinity"]     | "Carrie-Anne Moss"   |
| "The Matrix" | 1999       | ["Morpheus"]    | "Laurence Fishburne" |
| "The Matrix" | 1999       | ["Agent Smith"] | "Hugo Weaving"       |
| "The Matrix" | 1999       | ["Neo"]         | "Keanu Reeves"       |
+--------------------------------------------------------------------+
5 rows
25 ms
```

**その5**

```text
$ MATCH (m {title:'The Matrix'})<-[r:DIRECTED]-(c) RETURN m.title, m.released, r, c.name;
+----------------------------------------------------------------+
| m.title      | m.released | r               | c.name           |
+----------------------------------------------------------------+
| "The Matrix" | 1999       | :DIRECTED[60]{} | "Lana Wachowski" |
| "The Matrix" | 1999       | :DIRECTED[59]{} | "Andy Wachowski" |
+----------------------------------------------------------------+
2 rows
41 ms
```

* その4を若干修正したものです。
* mに対してDIRECTEDというタイプのリレーションを持つノードを検索します。

**その6**

```text
$ MATCH (m)<-[r:DIRECTED]-(c) WHERE m.title = "The Matrix" RETURN m.title, m.released, r, c.name;
+----------------------------------------------------------------+
| m.title      | m.released | r               | c.name           |
+----------------------------------------------------------------+
| "The Matrix" | 1999       | :DIRECTED[60]{} | "Lana Wachowski" |
| "The Matrix" | 1999       | :DIRECTED[59]{} | "Andy Wachowski" |
+----------------------------------------------------------------+
2 rows
24 ms
```

* その4を若干修正したものですが選択結果は変わりません。
* WHERE句でノードの選択条件を指定することができます。

```text
MATCH (m:Movie) WHERE m.title = 'The Matrix' OR m.title = 'The Matrix Reloaded' RETURN m.tagline;
+-----------------------------+
| m.tagline                   |
+-----------------------------+
| "Welcome to the Real World" |
| "Free your mind"            |
+-----------------------------+
2 rows
58 ms
```

* WHERE句で論理演算子を使うことができます。

**その7**

```text
$ MATCH (m) WHERE id(m) = 52 RETURN m;
+--------------------------------------------------------------------------------+
| m                                                                              |
+--------------------------------------------------------------------------------+
| Node[52]{title:"The Matrix",released:1999,tagline:"Welcome to the Real World"} |
+--------------------------------------------------------------------------------+
1 row
14 ms
```

* 検索条件にノードIDを指定することができます。

**その8**

```text
neo4j-sh (?)$ MATCH (m) WHERE m:Movie RETURN m.title, m.released ORDER BY m.released;
+------------------------------------------------+
| m.title                           | m.released |
+------------------------------------------------+
| "One Flew Over the Cuckoo's Nest" | 1975       |
| "Top Gun"                         | 1986       |
...省略...
| "Hoffa"                           | 1992       |
| "Cloud Atlas"                     | 2012       |
+------------------------------------------------+
38 rows
84 ms
```

* ORDER BY句でノードの並び順を指定することができます。


#### ノード、リレーション作成の例

**その1**

```text
$ CREATE (:Movie {title:'The Castle of Sand', released:1974, ean:4988105046207, storyline:'Detectives investigate the murder of an old man found in a Tokyo rail yard.'});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 4
Labels added: 1
7 ms
```

* title,released,ean,storylineというプロパティを持つノードを作成します。
* そのノードにMovieというラベルを付けます。

```text
$ CREATE (:Person {name:"Tetsuro Tanba", born:1922});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 2
Labels added: 1
11 ms
```

* name,bornというプロパティを持つノードを作成します。
* そのノードにPersonというラベルを付けます。

```text
$ MATCH (p:Person {name:'Tetsuro Tanba'}), (m:Movie {title:'The Castle of Sand'})
> CREATE (p)-[:ACTED_IN {roles:["Imanishi"]}]->(m);
+-------------------+
| No data returned. |
+-------------------+
Relationships created: 1
Properties set: 1
28 ms
```

* Personラベルが付いたnameプロパティが'Teturo tanba'であるノードを検索し、識別子pで参照できるようにします。
* Movieラベルが付いたtitleプロパティが'The Castle of Sand'であるノードを検索し、識別子mで参照できるようにします。
* pからm向きのrolesプロパティを持つリレーションを作成します。
* そのリレーションにACTED_INというタイプを付けます。

```text
$ MATCH (m)<-[r:ACTED_IN]-(c) WHERE m.title = "The Castle of Sand" RETURN m.title, m.released, r, c.name;
+------------------------------------------------------------------------------------------+
| m.title              | m.released | r                                  | c.name          |
+------------------------------------------------------------------------------------------+
| "The Castle of Sand" | 1974       | :ACTED_IN[308]{roles:["Imanishi"]} | "Tetsuro Tanba" |
+------------------------------------------------------------------------------------------+
1 row
20 ms
```

* 作成したノードを検索します。

**その2**

その1では作成を3つの処理に分けましたが1つにまとめることもできます。
そのためには識別子を用いて後続の処理から参照できるようにする必要があります。

```text
$ CREATE (m:Movie {title:'Suspicion', released:1982, ean:4988105046368})
> CREATE (p:Person {name:"Kensaku Morita", born:1949})
> CREATE (p)-[:ACTED_IN {roles:["Fujihara"]}]->(m);
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 2
Relationships created: 1
Properties set: 6
Labels added: 2
31 ms
```

* title,released,eanプロパティを持つノードを作成します。
* そのノードにMovieラベルを付けます。
* そのノードを識別子mで参照できるようにします。
* name,bornプロパティを持つノードを作成します。
* そのノードにPersonラベルを付けます。
* そのノードを識別子pで参照できるようにします。
* pからm向きのrolesプロパティを持つリレーションを作成します。
* そのリレーションにACTED_INというタイプを付けます。

```text
$ MATCH (m)<-[r:ACTED_IN]-(c) WHERE m.title = "Suspicion" RETURN m.title, m.released, r, c.name;
+----------------------------------------------------------------------------------+
| m.title     | m.released | r                                  | c.name           |
+----------------------------------------------------------------------------------+
| "Suspicion" | 1982       | :ACTED_IN[310]{roles:["Fujihara"]} | "Kensaku Morita" |
+----------------------------------------------------------------------------------+
1 row
23 ms
```

* 作成したノードを検索します。

**その3**

ノードの作成にはmerge句を使用することができます。
ただし条件にマッチするノードが存在しない場合になります。

```text
$ MERGE (:Person {name:'Ken Ogata', born:1937});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 2
Labels added: 1
32 ms
```

続けて同じ処理を実行します。

```text
$ MERGE (:Person {name:'Ken Ogata', born:1937});
+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+
21 ms
```

ただし、プロパティを追加するつもりで下記の処理を実行すると新しいノードが作成されてしまいます。

```text
$ MERGE (:Person {name:'Ken Ogata', born:1937, birthplace:'tokyo'});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 3
Labels added: 1
45 ms
```

```text
$ MATCH (p:Person {name:'Ken Ogata'}) return p;
+--------------------------------------------------------+
| p                                                      |
+--------------------------------------------------------+
| Node[5]{name:"Ken Ogata",born:1937}                    |
| Node[6]{name:"Ken Ogata",born:1937,birthplace:"tokyo"} |
+--------------------------------------------------------+
2 rows
30 ms
```

**その4**

ノードの作成時にのみプロパティを追加するにはMERGE句のON CREATE SETを使用します。

```text
$ MERGE (p:Person {name:'Shinichi Chiba', born:1939, birthplace:'fukuoka'}) ON CREATE SET p.created = timestamp() RETURN p;
+-------------------------------------------------------------------------------------+
| p                                                                                   |
+-------------------------------------------------------------------------------------+
| Node[8]{name:"Shinichi Chiba",born:1939,birthplace:"fukuoka",created:1438425901615} |
+-------------------------------------------------------------------------------------+
1 row
Nodes created: 1
Properties set: 4
Labels added: 1
48 ms
```

**その5**

ノードのプロパティを更新するにはMERGE句のON MATCH SETを使用します。

```text
$ MERGE (p:Person { name:'Tetsuro Tanba' }) ON MATCH SET p.birthplace = 'tokyo' RETURN p;
+------------------------------------------------------------+
| p                                                          |
+------------------------------------------------------------+
| Node[1]{name:"Tetsuro Tanba",born:1922,birthplace:"tokyo"} |
+------------------------------------------------------------+
1 row
Properties set: 1
58 ms
```

* Personラベルが付いたnameプロパティが'Tetsuro Tanba'であるノードを検索する。
* そのノードを識別子pで参照できるようにする。
* pで参照できるノードがあれば、そのノードにbirthplaceプロパティを追加する。
* pで示すノードを返す。

**その6**

これはエラーになる例です。
ノードとノードのリレーションを作成する場合は、リレーションの向きを指定する必要があります。

```text
$ CREATE (m:Movie {title:'Seven Samurai', released:1954, ean:4988104021175, tagline:'Will Take Its Place With the Seven Greatest Films of All Time!'})
> CREATE (p:Person {name:'Toshiro Mifune', born:1920})
> CREATE (p)-[:ACTED_IN {roles:['Kikuchiyo']}]-(m);
QueryExecutionKernelException: Only directed relationships are supported in CREATE (line 3, column 13 (offset: 216))
"  CREATE (p)-[:ACTED_IN {roles:['Kikuchiyo']}]-(m)"
             ^
```

#### ノード、リレーション削除の例

**その1**

```text
MATCH (m)<-[r:ACTED_IN]-(c) WHERE m.title = "Suspicion" DELETE m,r,c;
```

* WHERE句で検索する条件を指定します。
* 識別子m,r,cに参照するノードやリレーションを削除します。

**その2**

```text
MATCH (p:Person) WHERE id(p) = 6 DELETE p;
```

* ノードのIDを指定して削除します。

**その3**

```text
$ MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r
```

* すべてのノードとリレーションを削除します


#### プロパティの削除

**その1**

```text
$ MATCH (m)<-[r:ACTED_IN]-(c) WHERE m.title = "Suspicion" REMOVE m.ean;
+-------------------+
| No data returned. |
+-------------------+
Properties set: 1
52 ms
```

* 識別子mで参照するノードのeanプロパティを削除します。


#### 関数

##### id

```text:Syntax
ID( property-container )
```

id()関数でノードやリレーションのIDを取得することができます。

```text:example
$ MATCH (m:Movie) WHERE m.title = 'Suspicion' RETURN id(m);
+-------+
| id(m) |
+-------+
| 229   |
+-------+
1 row
25 ms
```

##### nodes

```text:Syntax
NODES( path )
```

nodes()関数でパスに含まれるノードをすべて取得することができます。

```text:example
$ MATCH p = (m)<-[r:ACTED_IN]-(c) WHERE m.title = "Suspicion" RETURN nodes(p);
+-----------------------------------------------------------------------------------------------------------+
| nodes(p)                                                                                                  |
+-----------------------------------------------------------------------------------------------------------+
| [Node[229]{title:"Suspicion",released:1982,ean:4988105046368},Node[230]{name:"Kensaku Morita",born:1949}] |
+-----------------------------------------------------------------------------------------------------------+
1 row
26 ms
```


##### relationships

```textSyntax
RELATIONSHIPS( path )
```

relationships()関数でパスに含まれるリレーションをすべて取得することができます。

```text:example
$ MATCH p = (m)<-[r:ACTED_IN]-(c) WHERE m.title = "Suspicion" RETURN relationships(p);
+--------------------------------------+
| relationships(p)                     |
+--------------------------------------+
| [:ACTED_IN[310]{roles:["Fujihara"]}] |
+--------------------------------------+
1 row
80 ms
```


##### labels

```text:Syntax
LABELS( node )
```

labels()関数でノードに付けられたラベル名を取得することができます。

```text:example
$ MATCH (m) WHERE id(m) = 229 RETURN m, labels(m);
+--------------------------------------------------------------------------+
| m                                                            | labels(m) |
+--------------------------------------------------------------------------+
| Node[229]{title:"Suspicion",released:1982,ean:4988105046368} | ["Movie"] |
+--------------------------------------------------------------------------+
1 row
31 ms
```


##### type

```text:Syntax
TYPE( relationship )
```

type()関数でリレーションに付けられたタイプ名を取得することができます。

```text:example
$ MATCH (m)<-[r:ACTED_IN]-(c) WHERE m.title = "The Castle of Sand" RETURN labels(m), labels(c), type(r);
+-------------------------------------+
| labels(m) | labels(c)  | type(r)    |
+-------------------------------------+
| ["Movie"] | ["Person"] | "ACTED_IN" |
+-------------------------------------+
1 row
22 ms
```


##### timestamp

```text:Syntax
TIMESTAMP()
```

timestamp()関数でUNIX epochをミリ秒で取得することができます。

```text:example
$ RETURN timestamp();
+---------------+
| timestamp()   |
+---------------+
| 1438296896634 |
+---------------+
1 row
9 ms
```

## その他

**Neo4j - github**

[Neo4j] (https://github.com/neo4j)

**Example Dataset**

[Example Dataset] (http://neo4j.com/developer/example-data/)

> There’s lots of example datasets for Neo4j. This guide outlines some of them.

**Java-neo4j-client**

[Java-neo4j-client] (http://inner-loop.github.io/java-neo4j-client/)

> A compact Neo4J Java API for connecting to non embedded instances.

**gremlin-plugin**

[gremlin-plugin] (https://github.com/neo4j-contrib/gremlin-plugin)

> A Plugin for the Neo4j server add Tinkerpop-related functionality

**tinkerpop**

[tinkerpop] (https://github.com/tinkerpop/blueprints/wiki/Neo4j-Implementation)

**Neo4j Tutorial**

[Neo4j Tutorial] (http://www.tutorialspoint.com/neo4j/index.htm)

> This tutorial will teach you basics of Neo4j, Java with Neo4j and Spring DATA with Neo4j. The tutorial is divided into sections such as Neo4j Introduction, Neo4j CQL, Neo4j CQL Functions, Neo4j Admin, Neo4j with Java and Neo4j with Spring DATA Framework. Each of these sections contain related topics with simple and useful examples.