中国語学習×グラフデータベース(13) - 細々気づいたこと

一通りデータは登録してみたので、細々したことをいくつか。

重複ノードの削除

データを登録する際に、いろいろ間違えてしまい不要なノードを削除したいなという時があった。通常のリレーショナルDB(以下RDB)では、テーブル定義の時にキーの重複を許さないように設定しておけば良いが、Neo4jを触った限りでは、単一項目での重複を許さないという設定は出来るものの、例えば単語(Word)のように、keywordとpinyinの組み合わせでの重複を許さないというような設定は出来ない(ように見える)。

今回の取り組みの中でも、自分の作ったコードの考慮が足りなかったために、同じ単語のノードが重複したときの削除に少しハマった。

で、どうしたらいいかをいろいろググると、StackoverflowではSKIPを使う方法が紹介されていたが、直感的にイマイチだと思ったので、ここに注目してみた。

f:id:deutschina:20160307151715p:plain

わかりにくいと思うが、どのNodeにもという属性が振られていた。これもCypherで拾えるだろと思っていたら、id()という表現を使えば良いらしいことが分かったので、こんなCypherクエリを実行してみた。

match (w1:Word {autoadd:True}), (w2:Word {autoadd:True}) where w1.keyword=w2.keyword and id(w1)<id(w2) return w2.keyword, id(w1), id(w2)

これは算数の問題だが、普通にやると単語の組み合わせが無数にある(5800の2乗で3000万通り以上)ため、処理に恐ろしく時間がかかるのだが、自分の場合、この手の重複はautoadd=Trueで登録した単語に限られることが分かっていたので、そこで絞り込むことができた。

2つの単語のidを比較して、単語(keyword)は同じだがidが異なる(どちらか一方を消せば良いので、<でさらに絞っている)を出力してくれと実行すると、消すべきidが4つほどに絞り込まれたので、今度はこんなcypherクエリを実行した。

match (w:Word)-[r:is_similar_to]-(w2:Word) where id(w) in [6458, 6461, 6469, 6497] delete w, r

Neo4jでは、Nodeの消去を行うには、Relationshipに紐付いていない事という条件があるため、Relationshipも同時に削除しなくてはならないので、こんな書き方をしている。実行結果は、こんな感じ。

Deleted 4 nodes, deleted 14 relationships, statement executed in 98 ms.

Node 4つに加えて、Relationshipが14個も削除されたことが分かる。上の2つは、Webインターフェイスから直接Cypherクエリを実行したが、もちろんgraph.cypher.execute()でpython側から実行しても結果は同じだ。

すべてが嫌になったときは

前も書いたが、これですべて消せる。

graph.delete_all()

消すなんてもったいないと思うかもしれないが、Jupyter Notebookでログを残しながらやっていれば、同じコードを再実行するのは簡単なので、結構あっさりと復元できるはずだ。

一通り、今回触ってきた内容については、ブログ上で整理したつもり。また何か進捗があれば、ここに書いていく予定。

(つづくかも)


グラフ型データベース入門 - Neo4jを使う

グラフ型データベース入門 - Neo4jを使う

グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門

グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門

A Programmatic Introduction to Neo4j

A Programmatic Introduction to Neo4j