Neo4j Cypher Refcard 2.2.1の訳です。読みやすいよう原文の内容を変えている箇所もあるので、正確な内容については必ず原文で確認を取るようにしてください。
Cypherは、世界有数のグラフデータベースであるNeo4j向けの宣言型クエリ言語です。
Cypherの基本事項および機能は以下の通りです。
- Cypherはグラフ内のノードおよびリレーションシップのパターンのマッチングを行い、データの取得と編集を行います。
- Cypherにはバインドされた要素とパラメータを意味する識別子の概念があります。
- Cypherはノード、リレーションシップ、ラベル、およびプロパティの生成、更新、削除を行うことができます。
- Cypherはインデクスと制約を管理します。
Neo4jコンソール(console.neo4j.org)でCypherスニペットを試すことができます。完全なドキュメントはNeo4jマニュアルを確認してください。Cypherを使ったライブグラフモデルはGraphGistを確認してください。
注:{value} はリテラル(アドホックCypherクエリ)もしくは、パラメータ(アプリケーション向けのベストプラクティス)の両方の意味があります。Neo4jのプロパティは「文字列」「数値」「Boolean」およびそれらの配列で構成されます。Cypherはマップとコレクションをサポートします。
構文
読み取り用クエリ構文
[MATCH WHERE]
[OPTIONAL MATCH WHERE]
[WITH [ORDER BY] [SKIP] [LIMIT]]
RETURN [ORDER BY] [SKIP] [LIMIT]
MATCH
MATCH (n:Person)-[:KNOWS]->(m:Person)
WHERE n.name="Alice"
ラベルとプロパティを含むノードパターン。
MATCH (n)-->(m)
MATCHで使用される任意のパターン。
MATCH (n {name:'Alice'})-->(m)
ノードプロパティ付きのパターン。
MATCH p = (n)-->(m)
p にパスを割り当てます。
OPTIONAL MATCH (n)-[r]->(m)
オプションパターン、存在しないパートはNULLが返ります。
WHERE
WHERE n.property <> {value}
フィルタのための述語を使用します。WHEREは常にMATCH、OPTIONAL MATCH、WITH、およびSTART句で使用されます。使用された句によって、動作が異なります。
RETURN
RETURN *
すべての識別子の値を返します。
RETURN n AS columnName
結果のカラム名に別名を与えます。
RETURN DISTINCT n
重複を排除した行を返します。
ORDER BY n.property
結果でソートします。
ORDER BY n.property DESC
結果を逆順でソートします。
SKIP {skip_number}
指定した数だけ結果をスキップします。
LIMIT {limit_number}
結果のデータ数を制限します。
SKIP {skip_number} LIMIT {limit_number}
トップからの結果をスキップして結果のデータ数を制限します(ページネーション)。
RETURN count(*)
マッチした行数をカウントします。詳細はAggregationを参照してください。
WITH
MATCH (user)-[:FRIEND]-(friend)
WHERE user.name = {name}
WITH user, count(friend) AS friends
WHERE friends > 10
RETURN user
WITH構文はRETURNと似ています。クエリのパートを明示的に分け、次のパートに引き継ぐ識別子を宣言します。
MATCH (user)-[:FRIEND]-(friend)
WITH user, count(friend) AS friends
ORDER BY friends DESC
SKIP 1 LIMIT 3
RETURN user
WITHはORDER BY、SKIP、LIMITと一緒に使用することができます。
UNION
MATCH (a)-[:KNOWS]->(b)
RETURN b.name
UNION
MATCH (a)-[:LOVES]->(b)
RETURN b.name
全てのクエリの結果から重複を排除した結果を返します。結果のカラム型とカラム名は一致している必要があります。
MATCH (a)-[:KNOWS]->(b)
RETURN b.name
UNION ALL
MATCH (a)-[:LOVES]->(b)
RETURN b.name
重複行を含む全ての結果を返します。
書き込み専用クエリ構文
(CREATE [UNIQUE] | MERGE)*
[SET|DELETE|REMOVE|FOREACH]*
[RETURN [ORDER BY] [SKIP] [LIMIT]]
読み書き用クエリ構文
[MATCH WHERE]
[OPTIONAL MATCH WHERE]
[WITH [ORDER BY] [SKIP] [LIMIT]]
(CREATE [UNIQUE] | MERGE)*
[SET|DELETE|REMOVE|FOREACH]*
[RETURN [ORDER BY] [SKIP] [LIMIT]]
CREATE
CREATE (n {name: {value}})
プロパティ付きで単一ノードを作成します。
CREATE (n {map})
プロパティ付きで単一ノードを作成します。
CREATE (n {collectionOfMaps})
プロパティ付きで複数ノードを作成します。
CREATE (n)-[r:KNOWS]->(m)
ノード間に識別子のバインド付きでタイプと方向性のあるリレーションシップを作成します。
CREATE (n)-[:LOVES {since: {value}}]->(m)
ノード間にタイプ、方向性、およびプロパティ付きのリレーションシップを作成します。
MERGE
MERGE (n:Person {name: {value}})
ON CREATE SET n.created=timestamp()
ON MATCH SET
n.counter= coalesce(n.counter, 0) + 1,
n.accessTime = timestamp()
パターンのマッチングを行い、存在しなければ作成します。パラメータの更新はON CREATEとON MATCHを使用します。
MATCH (a:Person {name: {value1}}),
(b:Person {name: {value2}})
MERGE (a)-[r:LOVES]->(b)
MERGEはノード間にリレーションシップを探して見つからなければ作成します。
MATCH (a:Person {name: {value1}})
MERGE
(a)-[r:KNOWS]->(b:Person {name: {value3}})
MERGEはノードに接続されたサブグラフを探して見つからなければ作成します。
SET
SET n.property = {value},
n.property2 = {value2}
プロパティを更新もしくは作成します。
SET n = {map}
全プロパティをセットして置き換えます。既存のプロパティは全て削除されます。
SET n += {map}
プロパティを追加もしくは更新します。キーが被らない既存のプロパティは保持されます。
SET n:Person
ノードにPersonラベルを追加します。
DELETE
DELETE n, r
ノードとリレーションシップを削除します。
REMOVE
REMOVE n:Person
ノードからラベルを削除します。
REMOVE n.property
プロパティを削除します。
INDEX
CREATE INDEX ON :Person(name)
Personラベルのプロパティnameにインデクスを作成します。
MATCH (n:Person) WHERE n.name = {value}
等値比較の際、自動的にインデクスが使用されます。lower(n.name) = {value}の場合はインデクスが使用されないことに注意してください。
MATCH (n:Person) WHERE n.name IN [{value}]
コレクションのチェックINでは自動的にインデクスが使用されます。
MATCH (n:Person)
USING INDEX n:Person(name)
WHERE n.name = {value}
次善のインデクスを使用する必要がある時、または複数のインデクスを使用する必要がある時、インデクスを強制的に使用することができます。
DROP INDEX ON :Person(name)
ラベルPersonのプロパティnameのインデクスを削除します。
CONSTRAINT
CREATE CONSTRAINT ON (p:Person)
ASSERT p.name IS UNIQUE
ラベルPersonのプロパティnameにユニーク制約を作成します。同じラベルのノードでnameが重複するような更新を行なった場合、操作は失敗します。制約を作成することにより付随的にインデクスが作成されます。
DROP CONSTRAINT ON (p:Person)
ASSERT p.name IS UNIQUE
ラベルPersonのプロパティnameからユニーク制約とインデクスを削除します。
インポート
LOAD CSV FROM
'http://neo4j.com/docs/2.2.1/cypher-refcard/csv/artists.csv' AS line
CREATE (:Artist {name: line[1], year: toInt(line[2])})
CSVファイルからデータを読み込み、ノードを作成します。
LOAD CSV WITH HEADERS FROM
'http://neo4j.com/docs/2.2.1/cypher-refcard/csv/artists-with-headers.csv' AS line
CREATE (:Artist {name: line.Name, year: toInt(line.Year)})
ヘッダ行付きCSVファイルからデータを読み込みます。
LOAD CSV FROM 'http://neo4j.com/docs/2.2.1/cypher-refcard/csv/artists-fieldterminator.csv'
AS line FIELDTERMINATOR ';'
CREATE (:Artist {name: line[1], year: toInt(line[2])})
フィールド区切りにカンマ以外の文字を使用します(周囲にホワイトスペース無し)
演算子
| 分類 | 演算子 |
|---|---|
| 数学 | +, -, *, /, %, ^ |
| 比較 | =, <>, <, >, <=, >= |
| Boolean | AND, OR, XOR, NOT |
| String | + |
| Collection | +, IN, [x], [x .. y] |
| 正規表現 | =~ |
NULL
-
NULLは存在しない、もしくは未定義の値の表現に使用されます。 -
NULLとNULLは等値ではありません。2つの値が不明なことは、それらが同じ値であることを意味しません。NULL = NULLはNULLとなり、TRUEにはなりません。NULLチェックする場合はIS NULLを使用してください。 - 算術式および、比較、関数呼び出し(
coalesceを除く)は引数がNULLの場合、NULLを返します。 - コレクションに要素が存在しない、プロパティが見つからない場合、これらにアクセスするとNULLが返ります。
-
OPTIONAL MATCH句では、パターン中に存在しないパートにNULLが使用されます。
パターン
(n)-->(m)
nからmへのリレーションシップが存在する。
(n:Person)
ラベルPersonを持つノードとマッチします。
(n:Person:Swedish)
ラベルPersonとSwedishを持つノードとマッチします。
(n:Person {name: {value}})
宣言されたプロパティを持つノードとマッチします。
(n:Person)-->(m)
ラベルPersonを持つノードnがmへのリレーションシップを持っています。
(n)--(m)
nとmの間に任意の方向のリレーションシップがあります。
(m)<-[:KNOWS]-(n)
nからmへ向かうタイプKNOWSのリレーションシップがあります。
(n)-[:KNOWS|LOVES]->(m)
nからmへ向かうタイプKNOWSまたはLOVESのリレーションシップがあります。
(n)-[r]->(m)
リレーションシップに識別子をバインドします。
(n)-[*1..5]->(m)
可変長のパス。
(n)-[*]->(m)
任意の深さ。パフォーマンスTips参照。
(n)-[:KNOWS]->(m {property: {value}})
MATCH、CREATE、CREATE UNIQUE、MERGE句でマッチもしくはプロパティをセットします。
shortestPath((n1:Person)-[*..6]-(n2:Person))
単一の最短パスを見つけます。
allShortestPaths((n1:Person)-[*..6]->(n2:Person))
全ての最短パスを見つけます。
ラベル
CREATE (n:Person {name:{value}})
ラベルとプロパティ付きのノードを作成します。
MERGE (n:Person {name:{value}})
ラベルとプロパティ付きのノードをマッチして存在しなければノードを作成します。
SET n:Spouse:Parent:Employee
ノードにラベルを追加します。
MATCH (n:Person)
ラベルPersonを持つノードとマッチします。
MATCH (n:Person)
WHERE n.name = {value}
指定されたプロパティnameと一致し、ラベルPersonを持つノードとマッチします。
WHERE (n:Person)
ノードのラベルの存在をチェックします。
labels(n)
ノードのラベル一覧を取得します。
REMOVE n:Person
ノードからラベルを削除します。
コレクション
['a','b','c'] AS coll
[]で括ることでコレクションのリテラルを宣言できます。
range({first_num},{last_num},{step}) AS coll
rangeは数値のコレクションを生成します(stepはオプション)コレクションを返す他の関数:labels、nodes、relationships、rels、filter、extract。
MATCH (a)-[r:KNOWS*]->()
RETURN r AS rels
可変長のパスのリレーションシップ識別子はリレーションシップのコレクションを含みます。
RETURN matchedNode.coll[0] AS value,
length(matchedNode.coll) AS len
プロパティは文字列、数値もしくはbooleanの配列/コレクションとなる場合があります。
coll[{idx}] AS value,
coll[{start_idx}..{end_idx}] AS slice
コレクションの要素は[idx]でアクセスすることができます。存在しない要素を指定した場合、NULLが返ります。
コレクションの要素はstart_idxとend_idxでアクセスすることもできます。負の値は末尾の要素からのインデクスです。
UNWIND {names} AS name
MATCH (n {name:name})
RETURN avg(n.age)
UNWINDを使用することで、コレクションを独立した行に変換することができます。例はnameのリスト内の全ての名前とマッチします。
マップ
{name:'Alice', age:38,
address:{city:'London', residential:true}}
{}で括ることでマップのリテラルを宣言できます。ネストしたマップとコレクションがサポートされています。
MERGE (p:Person {name: {map}.name})
ON CREATE SET p={map}
マップはパラメータとして渡すことができ、キーでアクセスすることができます。
MATCH (matchedNode:Person)
RETURN matchedNode
パターンにマッチしたノードとリレーションシップはマップとして返されます。
map.name, map.age, map.children[0]
マップの要素はキーによってアクセスすることができます。存在しないキーでアクセスするとエラーが発生します。
リレーションシップ関数
type(a_relationship)
リレーションシップのタイプの文字列表記です。
startNode(a_relationship)
リレーションシップの開始ノードです。
endNode(a_relationship)
リレーションシップの終端ノードです。
id(a_relationship)
リレーションシップの内部IDです。
述語
n.property <> {value}
比較演算子の使用。
has(n.property)
関数の使用。
n.number >= 1 AND n.number <= 10
述語を結合するためにBoolean演算子を使用します。
n:Person
ノードのラベルのチェック。
identifier IS NULL
NULLチェック。
NOT has(n.property) OR n.property = {value}
propertyが存在しない、または、述語が真です。
n.property = {value}
存在しないプロパティはNULLを返します。いかなる値とも一致しません。
n.property =~ "Tob.*"
正規表現。
(n)-[:KNOWS]->(m)
少なくとも1件のパターンとマッチすることを確認します。
NOT (n)-[:KNOWS]->(m)
(n)-[:KNOWS]->(m)にマッチするものを除外します。
n.property IN [{value1}, {value2}]
コレクション内に要素が存在するかどうかをチェックします。
コレクションの述語
all(x IN coll WHERE has(x.property))
コレクションのすべての要素について述語がTRUEの場合、trueを返します。
any(x IN coll WHERE has(x.property))
コレクションのうち少なくとも1件の要素がTRUEの場合、trueを返します。
none(x IN coll WHERE has(x.property))
コレクションのすべての要素について述語がFALSEの場合、trueを返します。
single(x IN coll WHERE has(x.property))
コレクションの一つの要素について述語がTRUEの場合、trueを返します。
関数
coalesce(n.property, {defaultValue})
コレクション中で最初に見つかったNULLでない値を返します。すべての要素がNULLの場合、NULLを返します。
timestamp()
1970年1月1日0時0分UTCからのミリ秒。
id(node_or_relationship)
リレーションシップもしくはノードの内部ID。
toInt({expr})
入力パラメータを整数に変換します。変換できない場合、NULLを返します。
toFloat({expr})
入力パラメータを浮動小数点数に変換します。変換できない場合、NULLを返します。
keys({expr})
ノードやリレーションシップのプロパティ名、もしくはマップのキーの文字列表記のコレクションを返します。
パス関数
length(path)
パスの長さを返します。
nodes(path)
パス上のノードをコレクションとして返します。
relationships(path)
パス上のリレーションシップをコレクションとして返します。
MATCH path=(n)-->(m)
WHERE id(n) = %A% AND id(m) = %B%
RETURN extract(x IN nodes(path) | x.prop)
パスを割り当て、そのノードを処理します。
MATCH path = (begin) -[*]-> (end)
WHERE id(begin) = %A% AND id(end) = %B%
FOREACH
(n IN rels(path) | SET n.marked = TRUE)
パスのそれぞれのリレーションシップに対して操作を実行します。
コレクション関数
length({coll})
コレクションの長さを取得します。
head({coll}), last({coll}), tail({coll})
headは最初の要素、lastは最後の要素を返します。tailはコレクションの残りの要素を返します。空のコレクションの場合、いずれもNULLを返します。
[x IN coll WHERE x.prop <> {value} | x.prop]
フィルタと展開で簡潔な表記の組み合わせです。
extract(x IN coll | x.prop)
元のコレクションのそれぞれの要素の値のコレクション。
filter(x IN coll WHERE x.prop <> {value})
述語がTRUEになる要素でフィルタされたコレクション。
reduce(s = "", x IN coll | s + x.prop)
コレクションの要素それぞれについて表現を評価し、結果を足し込みます。
FOREACH (value IN coll |
CREATE (:Person {name:value}))
コレクションの要素それぞれに対して操作を実行します。
数学関数
abs({expr})
絶対値。
rand()
ランダム値。呼び出しのたびに新しい値を返します。サブセットの選択やランダムソートに利用できます。
round({expr})
最も近い整数に値を丸めます。ceilは切り上げ、floorは切り捨てをします。
sqrt({expr})
平方根。
sign({expr})
ゼロの場合0、負の値の場合-1、正の値の場合1を返します。
sin({expr})
三角関数。他に、cos, tan, cot, asin, acos, atan, atan2, haversinも利用可能です。
degrees({expr}), radians({expr}), pi()
degreesラジアンを度に変換します。逆変換する場合radiansを利用します。piはπを算出します。
log10({expr}), log({expr}), exp({expr}), e()
常用対数、自然対数、指数、e。
文字列関数
toString({expression})
文字列表記。
replace({original}, {search}, {replacement})
searchに一致する文字列をreplacementで置換します。
substring({original}, {begin}, {sub_length})
部分文字列を取得します。sub_lengthはオプションです。
left({original}, {sub_length}),
right({original}, {sub_length})
先頭からの部分文字列と末尾からの部分文字列です。
trim({original}), ltrim({original}),
rtrim({original})
全てのホワイトスペース、左側および右側のホワイトスペースを取り除きます。
upper({original}), lower({original})
大文字、小文字。
split({original}, {delimiter})
文字列を指定した区切り文字で分割しコレクションを返します。
集計
count(*)
マッチした行数。
count(identifier)
NULLでない値の数。
count(DISTINCT identifier)
DISTINCT修飾子を適用することで重複する値を取り除いた上で集計を行います。
collect(n.property)
値の配列を返します。NULLは無視されます。
sum(n.property)
数値の合計。同様の関数として、avg、min、maxがあります。
percentileDisc(n.property, {percentile})
離散パーセンタイル。連続パーセンタイルはpercentileCont 。引数percentileは0.0〜1.0の範囲です。
stdev(n.property)
サンプル母集団を対象とした標準偏差。母集団全体を対象とした標準偏差を計算する場合stdevpを使用します。
CASE
CASE n.eyes
WHEN 'blue' THEN 1
WHEN 'brown' THEN 2
ELSE 3
END
WHENにマッチした場合、THENの値を返します。ELSEの指定は任意です。該当しない場合、NULLが返ります。
CASE
WHEN n.eyes = 'blue' THEN 1
WHEN n.age < 40 THEN 2
ELSE 3
END
最初にTRUEとなったWHENのTHENの値を返します。条件は順番に評価されます。
START
START n=node:nodeIndexName(key={value})
正確なクエリでnodeIndexNameという名前のインデクスを照会します。自動インデクスはnode_auto_indexを使用します。Cypher 2.2で、その他のSTARTのオプションは削除されました。
CREATE UNIQUE
CREATE UNIQUE
(n)-[:KNOWS]->(m {property: {value}})
パターンのマッチングを行い、存在しなければ作成します。パターンは一部を含んでもいけません。
パフォーマンス
- 可能であれば、リテラルではなくパラメータを使用してください。パラメータを使用することで、Cypherは新しい実行計画を解析および構築せずに、クエリを再利用します。
- 可変長パターンには常に上限を設定してください。誤ってグラフ内の全てのノードにアクセスしてしまうと、パフォーマンスを下げます。
- 必要なデータのみを返すようにしてください。全てのノードとリレーションシップを返さないようにしてください。
- クエリのパフォーマンスを解析するために
PROFILE/EXPLAINを使用してください。詳細はクエリチューニングを参照してください。