特に断りがない限り、環境はOSX、neo4jは3.4.5を参照。
REST APIの/user/<user name>/passwordに対してPOSTする。
curl -H "Content-Type: application/json" -XPOST -d '{"password":"new_password"}' -u your_name:old_password http://localhost:7474/user/your_name/password
CALL dbms.procedures()
neo4jがインストールされている場所のpluginsディレクトリにjarファイルを配置してneo4jサーバーをリスタートする。
brewからインストールした場合は/usr/local/Cellar/neo4j/3.4.5/libexec/pluginsが対象ディレクトリ。
サーバーの再起動は以下。
$ neo4j restart
先にノードをMATCHしてから、参照を使ってリレーションをCREATEする。
MATCH (m:A),(n:B) CREATE (m)-[:R]->(n);
次のようにノードの定義をCREATE文に含めると、リレーションと一緒にノードも作成されてしまう。
CREATE (m:A)-[:R]->(n:B);
SETを使用する。
MATCH (n:X) SET n.x = 1 RETURN n;
SETでノードを代入するとプロパティのコピーが行われる。ラベルのコピーまでは行われない点に注意。:
MATCH (n:Foobar) CREATE (copy:Foobar) SET copy = n;
REMOVEを使用する
MATCH (n) REMOVE n:Foobar;
SETで空オブジェクトを代入するとプロパティが全て削除される。
MATCH (n) SET n = {};
MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r;
MATCH ()-[e]-() DELETE e;
WHERE節を使用する。
MATCH (n) WHERE n.prop = "foobar" RETURN n;
ただし、対象プロパティにインデックスを張っておかないと検索が非効率なフルノードスキャンになってしまうのに注意。
MATCH (m)--(n) RETURN m, n;
ちなみに、(a)--(b)と(a)-[]-(b)は同じ意味になる。
MATCH (m)-[:A]-(n) RETURN m, n;
MATCH p=shortestPath((:A)-[*]-(:B)) RETURN p;
実用上は、検索対象が広がり過ぎないように最大長さを指定しておく。
MATCH p=shortestPath((:A)-[*..5]-(:B)) RETURN p;
INを使用する。
MATCH (user:User) WHERE user.name IN ['Joe', 'John', 'Sara', 'Maria', 'Steve'] RETURN user;
=~を使用する。対象文字列の全体にマッチさせる必要がある点に注意。
MATCH (user:User) WHERE user.name =~ 'St.*' RETURN user;
特定の正規表現にマッチしないことを条件にする場合はNOTを使用する。
MATCH (user:User) WHERE NOT (user.name =~ 'St.*') RETURN user;
existsを使用する。
MATCH (n) WHERE exists(n.foobar) RETURN n;
nodesでマッチしたサブグラフのノード集合を取得し、ALLで全てのノードに必要な条件を記述する。
MATCH p =(a)-[*1..3]->(b)
WHERE a.name = 'Alice' AND b.name = 'Daniel' AND ALL (x IN nodes(p) WHERE x.age > 30)
RETURN p;
relationshipsでマッチしたサブグラフのリレーション集合を取得し、ALLで全てのに必要な条件を記述する。
MATCH (ms:Person { name: 'Martin Sheen' }),(cs:Person { name: 'Charlie Sheen' }), p = shortestPath((ms)-[:ACTED_IN*]-(cs))
WHERE ALL (r IN relationships(p) WHERE exists(r.role))
RETURN p;
UNIONを使用して複数のMATCHした結果を合成する。
MATCH (n:Male)
RETURN n
UNION MATCH (n:Female)
RETURN n;
以下のようにOR条件で簡潔に検索することも出来る。
MATCH (n) WHERE n:Male OR n:Female RETURN n;
通常はこちらの方法で問題ない。ただし、古いバージョンのneo4jではノードのフルスキャンが発生する可能性がある。実際にどうなるかPROFILEでプランを確認しておくとよい。
PROFILE MATCH (n) WHERE n:Male OR n:Female RETURN n;
https://stackoverflow.com/questions/20003769/neo4j-match-multiple-labels-2-or-more
ソースノードに対してクエリを行い、-[*]->で任意の長さのパスを指定する。
MATCH (n)-[*]->(m) WHERE n.id = "foobar" RETURN n, m;
ただし、グラフの規模によっては高負荷になる可能性があるため、なるべく深さを制限するようなクエリにした方がよい。
MATCH (n)-[*..3]->(m) WHERE n.id = "foobar" RETURN n, m;
count(*)はマッチしたノードを数え上げる。
MATCH (n) RETURN count(*);
-[*]->は接続を長さ別に全て数え上げてパスを返すので、DISTINCTで重複を排除してCOUNTする必要がある。
MATCH (n)-[*]->(m) WHERE n.id = "foobar" RETURN COUNT(DISTINCT m);
nodesでパスからノードを抽出する方法も使える。
MATCH p = (n)-[*]->(m) WHERE n.id = "foobar" RETURN COUNT(nodes(p));
ラベルを集約する。
MATCH (n)
RETURN DISTINCT labels(n);
ただしこれは、正確には「ノードに割り当てられている全ての複合ラベルの組み合わせ」となる。単体のラベルに分けて一覧したい場合は、db.labels()を使用する。
CALL db.labels();
ちなみにbrowserのDatabase Informationタブにも一覧が表示されている。
リレーションには一つのタイプしか割り当てられないため、集約で全種類が調べられる。
MATCH ()-[r]-()
RETURN DISTINCT type(r);
または、
CALL db.relationshipTypes();
WHEREでパスを条件にして絞り込む。
MATCH (n) WHERE NOT (n)-->() RETURN n;
長さが丁度3つ
MATCH p = ()-[:*3]->() RETURN p;
3つ以上の場合
MATCH p = ()-[:*3..]->() RETURN p;
3つ以下の場合
MATCH p = ()-[:*..3]->() RETURN p;
3つ以上5つ以下の場合
MATCH p = ()-[:*3..5]->() RETURN p;
パスではなく、(a)-[r]->(b)の形で一行ずつ結果を処理したい場合は、最初にパスをマッチしてからサブクエリで1対1の関係をマッチさせる。
MATCH p = (n)-[*]->(m) WHERE n.id = 'Start' WITH DISTINCT p, m AS b MATCH (a)-[r]->(b) WHERE a in nodes(p) RETURN a,r,b;
|でタイプを区切る。
MATCH p = (m)-[:A|B*]->(n) RETURN p;
それぞれのタイプの共通プロパティであれば検索条件に含めることが出来る。
MATCH p = (m)-[:A|B* { id: "foo" }]->(n) RETURN p;
ラベルとプロパティを指定してインデックスを作成する。RDBMSと同様に、書き込み速度とディスクスペースを犠牲にして、そのプロパティを使った検索を高速化させる。
CREATE INDEX ON :Foobar(id);
複合インデックスはカンマ区切りで指定する。
CREATE INDEX ON :Foobar(id, name);
インデックスはバックグラウンドで作成されるため、直後ではまだ有効になっていない場合がある。
インデックスの作成ステートもこれで調べられる。
CALL db.indexes()
ラベルとプロパティ名を指定して削除する。
DROP INDEX ON :Foobar(id);
CREATE CONSTRAINT ON (n:Node) ASSERT n.id IS UNIQUE;
複合キーのユニーク制約はenterpriseバージョンのNODE KEY機能が必要。
制約を削除するには同じ条件でDROP CONSTRAINTを使用する。
DROP CONSTRAINT ON (n:Node) ASSERT n.id IS UNIQUE;
インデックスはラベルを通して働くため、無条件で全てのノードにインデックスを張ることは出来ない。そこで、インデックス用のラベルを全てのノードに共通で持たせて、そのプロパティを対象賭する。
MATCH (n) SET n:Index
CREATE INDEX ON Index(id);
ここで作ったラベルを検索時に含めないと、インデックスが働かない点に注意する必要がある。PROFILEを使ってクエリにインデックスが効いているかどうかを確認するとよい。
ネイティブなクエリではサポートされていないので、APOCを使う。
CALL apoc.schema.assert({}, {})
または、REST APIでラベルとプロパティを取得して、スクリプトでDROPクエリを発行する。
https://stackoverflow.com/a/26077913