LoginSignup
4
3

Cypher備忘録

Last updated at Posted at 2022-12-11

基本

  • ノードは括弧 () で表される。
  • ラベルはコロンで表し、例えば (:Person) とします。
  • ノード間の関係は2本のダッシュで記述します。 (:Person)--(:Movie)
  • リレーションシップの方向は、大なり小なり記号 < または > を用いて示されます。 (:Person)-→(:Movie)
  • リレーションシップのタイプは、2つのダッシュの間にある角括弧 [ と ] を使って記述されます。
  • プロパティは、JSONのような構文で指定されます。
  • ノードを取得したい場合には、コロンの前に値(下記の例では p) を置くことで、変数を代入することができます。
MATCH (p:Person)
  • Neo4jのプロパティはキーと値のペアで、例えば {name: 'Tom Hanks'} のようになります。
// example Cypher pattern
(m:Movie {title: 'Cloud Atlas'})<-[:ACTED_IN]-(p:Person)
  • dot記法 を使ってプロパティにアクセスできます
MATCH (p:Person {name: 'Tom Hanks'})
RETURN  p.born
  • Cypherでは、ラベル、プロパティ・キー、変数は、大文字と小文字が区別されます。
  • Cypherのキーワードは、大文字と小文字が区別されません

お作法

  • ラベルにはCamelCase (先頭の文字を大文字で表記)を使用して名前を付けます。
  • プロパティキーと変数にcamelCase (先頭は小文字、後続する単語の先頭は大文字で表記)を使用した名前を付けます。
  • Cypherキーワード(MATCH, WHERE 等)には、UPPERCASE(すべて大文字)を使用します。
  • ノードのラベルは最低でも1つ、最大でも4つまでとするのがベストプラクティスです。
  • Index名は ノード名_プロパティー

index

index作成

# 単体index
CREATE INDEX <インデックス名> IF NOT EXISTS FOR (n:ノード名) ON (n.プロパティー名);

# 複合indexの場合
CREATE INDEX <インデックス名> IF NOT EXISTS FOR (n:ノード名) ON (n.プロパティー名1, n.プロパティー名2, ・・・);

index削除

DROP INDEX インデックス名;

インデックス一覧の取得

show indexes

プロパティー一覧の取得方法(keys)

MATCH (p:Person)
RETURN p.name, keys(p)

グラフに存在するプロパティは何か?

一度定義したプロパティ・キーは、そのプロパティ・キーを使用するノードやリレーションシップが現在存在しない場合でも、グラフ内に残ります。

CALL db.propertyKeys()

グラフに存在するラベル一覧の取得

CALL db.labels()

リレーションの一覧

インデックスが貼れないから重い?

match (a)-[r]->(b) return distinct a.labels, type(r), b.labels

制約一覧の取得

show constraints

MERGE

Cypher の超主力キーワード
MERGE は、まずデータの存在確認を行い、存在していなければ作成し、既に存在していれば作成しない
便利だが、MERGE内で複数ノード、リレーションを作成する場合、一つでも未作成のオブジェクトがあると作成してしまう
(プライマリーキー制約があれば失敗するが、そうでなければ、同じオブジェクトが複数さくせいされてしまう。)

MERGE のカスタマイズ

ノードが作成されたときやノードが見つかったときにプロパティを設定できるように、実行時の振る舞いを指定することができる。
ON CREATE SETON MATCH SET 条件、あるいは SET キーワードを使って、任意の追加プロパティを設定することができます。

// 存在しなければ作成、既に存在すれば参照を返す
MERGE (p:Person {name: 'McKenna Grace'})

// ノードが作成された場合  `createdAt` プロパティーを作成
ON CREATE SET p.createdAt = datetime()

// ノードが既に存在していれば `updatedAt` プロパティーを設定
ON MATCH SET p.updatedAt = datetime()

// プロパティーの有無に関わらず `born` プロパティーを設定ト
SET p.born = 2006

RETURN p

検索

書き方色々

MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE m.title='The Matrix'
RETURN p.name
MATCH (p)-[:ACTED_IN]->(m)
WHERE p:Person AND m:Movie AND m.title='The Matrix'
RETURN p.name

部分一致によるフィルタリング

MATCH (p:Person)-[:ACTED_IN]->()
WHERE toLower(p.name) STARTS WITH 'michael'
RETURN p.name

リストによるフィルタリング

MATCH (p:Person)
WHERE p.born IN [1965, 1970, 1975]
RETURN p.name, p.born

INなら動くけど、=だと動かない

リレーションのプロパティーに対しては条件を指定できない?

MATCH (p:Person)-[r:ACTED_IN]->(m:Movie)
WHERE  'Neo' IN r.roles AND m.title='The Matrix'
RETURN p.name, r.roles
MATCH (p:Person)-[r:ACTED_IN]->(m:Movie)
WHERE  'Neo' = r.roles AND m.title='The Matrix'
RETURN p.name, r.roles

全ノード取得

MATCH (a) RETURN a

with句

購入数が2以上のノード(User、Item)、リレーション数(購入数)を抽出

MATCH (a:User)-[r:BUY]->(b:Item)
WITH a,b,count(r) as cnt
WHERE cnt >= 2
RETURN *

リレーションの情報は取れない模様(下記だヒットしない)

MATCH (a:User)-[r:BUY]->(b:Item)
WITH a,b, r, count(r) as cnt
WHERE cnt >= 2
RETURN *

Index一覧取得

show indexes

制約一覧取得

show constraints

ソート

RETURN の後に ORDER By

MATCH (n)
RETURN n.name, n.age
ORDER BY n.name

複数カラムに対して重複削除

期待通りに distinct が使える

MATCH (n:User) RETURN distinct n.sex , n.age;

ラベルの追加

MATCH (p:Person {name: 'Jane Doe'})
SET p:Developer
RETURN p

カウント

全ノードの件数

MATCH (n) RETURN count(*);

ノードの種類を特定してカウント

MATCH (u:User) RETURN count(*);

リレーションの数

MATCH ()-[r]->() RETURN count(r) as count;

ノード間を特定してカウント

MATCH (a:Company)-[r]->(b:User) RETURN count(r) as count;

リレーションを特定してカウント

MATCH ()-[r:BUY]->() RETURN count(r) as count;

ノードの種類を特定してカウント

MATCH (u:User) RETURN count(*);

削除

全削除

MATCH (n) DETACH DELETE n

オブジェクトの参照を取得してからDELETEで削除

MATCH (p:Person)
WHERE p.name = 'Jane Doe'
DELETE p

リレーションが単体で存在させる事を防ぐため、リレーションが張られているノードを削除しようとするとエラーになる

Cannot delete node<ノードID>, because it still has relationships. To delete this node, you must first delete its relationships.

ノードとリレーションの削除

DETACHを使う

MATCH (p:Person {name: 'Jane Doe'})
DETACH DELETE p

ラベルの削除

MATCH (p:Person {name: 'Jane Doe'})
REMOVE p:Developer
RETURN p

IDを指定して削除

ノードの場合

id=1のノードを削除

MATCH (n) where id(n)=1 DELETE n

リレーションの場合

id=2の BUY リレーション を削除

MATCH ()-[r:BUY]->() where id(r)=1 DELETE r

リレーション削除

ユーザ(user_id=11111)と 商品(item_id: "22222")との関係(購入)を削除

MATCH (a:User{user_id: "11111"})-[r:BUY]->(b:Item{item_id: "22222"}) DELETE r;

プロパティの削除

ノードやリレーションシップからプロパティを削除するには、 REMOVE キーワードを使用するか、プロパティを null に設定する
ノードの主キーとして使用されているプロパティも削除できるが、やってはいけない

MATCH (p:Person)-[r:ACTED_IN]->(m:Movie)
WHERE p.name = 'Michael Cain' AND m.title = 'The Dark Knight'
REMOVE r.roles
RETURN p, r, m
MATCH (p:Person)
WHERE p.name = 'Gene Hackman'
SET p.born = null
RETURN p

indexの削除

DROP INDEX <index_name> IF EXISTS

ノードA-B間で重複しているリレーションを一意にする

apocで用意されている

MATCH (a:User)-[r:BUY]->(b:Item)
WITH collect(r) as cnt
WHERE size(cnt) > 1
CALL apoc.refactor.mergeRelationships(cnt) YIELD rel
RETURN COUNT(*)

DBのクローン

Neo4J Desktopの場合

DBの作成

CREATE DATABASE DB名;

DBの削除

sysytem データベースに切り替えてから実行する必要がある

DROP DATABASE DB名;

DB一覧

SHOW DATABASES;

DBを切り替える

:use <DB名>

DB停止

STOP DATABASE <DB名>

停止確認は

show databases;

から 対象DBが currentStatus=offline となっている事を確認

DB開始

start <DB名>

スキーマ確認

CALL db.schema.visualization()

dumpファイルのロード

sudo -u neo4j /usr/bin/neo4j-admin database load --overwrite-destination=false --from-path=<dumpファイルがか格納されているディレクトリへの絶対パス> <DB名> --verbose
  • DBはStopしておく必要あり
  • neo4j-adminへのパスが通っていれば /usr/bin/neo4j-admin -> neo4j-admin でOK(通っているはず)
  • dumpファイルは <DB名>.dump になっている必要あり
  • 既存の中身を差し替えたい場合は -overwrite-destination=true を指定
  • DBが既にある状態で -overwrite-destination=false を指定するとエラーになる
  • 4.4系で作成したDumpファイルは5.5系にエクスポートできない模様(フォーマット違うらしい)

Cypher ShellにDBを指定してログインする

ローカルのneo4jにポート 17687 でアクセスする場合

/usr/bin/cypher-shell -u <ユーザ名> -p <パスワード> -d <データベース名> -a neo4j://localhost:17687

cypherシェルからログアウト

:exit

confの場所

/etc/neo4j/neo4j.conf

登録・削除処理の途中でメモリ不足の落ちる場合は?

バッチサイズを指定して実行。parallelはTrueにすると速いが、メモリへの負担が大きい

CALL apoc.periodic.iterate(
やりたい処理
{batchSize:5000,parallel:false}
);

例)
明示的にRETURN を使ってやらないとbatchSizeが効かない模様( MATCH (n) DETACH DELETE n だけだと駄目)

CALL apoc.periodic.iterate(
  "MATCH (n) RETURN n",
  "DETACH DELETE n",
{batchSize:5000, parallel:False});

他で作成した dumpデータをDesktopに認識させる

windowsの場合、下記にdumpファイルを置くと認識してくれる

C:<設定による>\relate-data\projects\プロジェクトのIDっぽいフォルダ名

参照

Cypherの紹介

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3