雑多なノート

プログラミング初心者がメモとかを書きます。基礎的なこともメモとして。偏食系のアニオタ。

無かったら作成,有ったら更新(Neo4j)

neo4jには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()

MERGEで作成または検索するパターン設定でON CREATEが作成時のパラメーター設定,ON MATCH SETが更新時のパラメーター設定なんだろう
多分

ちなみにcoalesceは最初に見つけたNULLでない値を返す関数らしい
この場合だと値が未設定の場合0を設定するってことか
便利だな

とりあえずちょっと弄ってぶちこんで確認してみる

MERGE (n:Person {name: "Alice"}) ON CREATE SET n.created=timestamp() ON MATCH SET n.counter= coalesce(n.counter, 0) + 1, n.accessTime = timestamp()


f:id:vayacico:20161130190632j:plain
ノードが作成された
createdに現在の時刻(たぶん)が格納されたっぽい


2回目の実行
f:id:vayacico:20161130190646j:plain
accessTimeに時刻が設定されてカウンターが1になった



一応3回目
f:id:vayacico:20161130190653j:plain
どうやら思った通りに動いてる
これは便利だな

MATCH (a:Person {name: "Karen"}), (b:Person {name: "Alice"}) MERGE (a)-[r:LOVES]->(b) ON CREATE SET r.created=timestamp() ON MATCH SET r.counter= coalesce(r.counter, 0) + 1, r.accessTime = timestamp()

こんな感じでリレーションにも使えるみたい
便利

MySQLの実行結果を捨てる

実際の実行時間だけを知りたかったので実行結果を捨てる方法を調べた
スクリプトから実行する予定のクエリだけど結果を表示させるとコンソールがぐわーってなるし
pagerなるものを使えば良いらしい

mysql> pager cat >/dev/null

本来は出力結果を外部コマンドで見やすくするのに使うんだとか
これで件数と時間だけが表示される

mysql> select userid from tweet group by userid having count(*) > 5;
236595 rows in set (1 min 36.63 sec)

元に戻すときは

mysql > nopager

で戻るらしい


本当はEXPLAINとか使ってスマートに色々知れるんだろうけどよくわからなかったので

mysqldの自動起動

MySQLに接続しようとしたらエラー

ERROR 2002 (HY000): Can't connect to local MySQL 
server through socket '/var/lib/mysql/mysql.sock'
 (2)

なんで落ちてんだって思ったら自動起動設定忘れてた
この前neo4jのために再起動したからそのせいか
滅多に再起動しないから気づかなかった

$ sudo chkconfig mysqld on

とりあえずこれでOKなはず


CRONでTwitterからデータ持ってきてデータベースに入れるスクリプト走らせてたけどエラーなってた
当たり前だけど
むー


標準エラー出力をメールするように設定するかねー

REST::Neo4pを使ってみる

とりあえず適当に使ってみた
クエリを投げただけだけど
色々便利そうな関数用意されてるけど直接クエリ投げた方が個人的には分かりやすい気がする

use REST::Neo4p;

REST::Neo4p->connect('http://127.0.0.1:7474','USER_NAME','PASSWORD');

my $query = REST::Neo4p::Query->new('CREATE (Person{name:"アリス",from:"イギリス"})');
$query->execute;

何も考えずに日本語使えたのは驚き
PerlMySQLの組み合わせだと散々苦しめられたから覚悟してたんだけどな
Webの管理画面で見ても文字化けせずに見れるし大丈夫っぽい


関数一覧眺めてたら思ったより使いやすいかも
気が向いたら使ってみよう

REST::Neo4pのインストール

あんまりメジャーじゃないみたいだけどPerlからNeo4jを使いたかったのでモジュールをインストールした
探したら複数見つかったけど公式で紹介されてるREST::Neo4pを入れることにした
イマイチ使い方分からないけど
REST::Neo4p - A Perl "OGM" - Neo4j Graph Database

普通にcpanを使ってインストール

cpan[1]> install REST::Neo4p

途中でユーザーネームとパスワード聞かれたので入力したらテストが失敗した

Server for live tests: [http://127.0.0.1:7474 ]  
http://127.0.0.1:7474                            
Username: [ ] testuser                                              
Pass: [ ]testpass
Result: FAIL                                     
Failed 1/36 test programs. 1/1327 subtests failed
.                                                
  MAJENSEN/REST-Neo4p-0.3012.tar.gz              
  ./Build test -- NOT OK                         
//hint// to see the cpan-testers results for inst
alling this module, try:                         
  reports MAJENSEN/REST-Neo4p-0.3012.tar.gz      
Running Build install                            
  make test had returned bad status, won't instal
l without force                                  
Failed during this command:                      
 MAJENSEN/REST-Neo4p-0.3012.tar.gz            : m
ake_test NO

納得いかないけどここは何も入れずにエンターでいいみたい

Username: [ ]                                    
                      
Pass: [ ]
./Build install  -- OK


ただ単にテストをスキップしてるだけな気もするけどテストスクリプトを実行したら動いたので大丈夫かな

Neo4j起動時のWARNING

インストール直後から発生してるワーニング

[vayacico@lavie bin]$ ./neo4j start
Starting Neo4j.
WARNING: Max 1024 open files allowed, minimum of 40000 recommended. See the Neo4j manual.Started neo4j (pid 1358). By default, it is available at http://localhost:7474/
There may be a short delay until the server is ready.
See /opt/neo4j-community-3.0.7/logs/neo4j.log for current status.

よく分からないけど開けるファイルの数が制限されてるからどうにかしろってことらしい
そんなにファイル開くのかコイツ
ワーニング出てても動くけど忘れたころに謎のエラーとして現れても嫌なので治す

ググってみたら設定ファイルに追記すればいいらしい


/etc/security/limits.conf

vayacico        hard        nofile        100000
vayacico        soft        nofile        40000
root            hard        nofile        100000
root            soft        nofile        40000

/etc/pam.d/su

session    required   pam_limits.so

Qiitaの記事だとユーザー名のところがneo4jになってたのでそこがユーザー名だということに気づくのに時間がかかった
よく考えればrootと同じところに書かれてるのでユーザー名なのは当たり前だった

あと再起動しないと適用されなかった
CRONで動かしてるスクリプトがあったから極力再起動したくなかったけど他の方法見つからなかったので仕方ない

とりあえずこれでワーニングは解消

Neo4jを弄ってみた

なんとかブラウザからアクセスできるようになったのでいろいろいじってみた

ログインした画面の上にあるボックスにクエリをそのままぶち込めば実行できるっぽい
気軽で便利かも
シェルみたいに履歴機能ついてるし色つけもやってくれるのがうれしい

ノードの作成
CREATE (a:Person{name:"Alice",From:"Britain"})

これでイギリス出身のアリスノードができるらしい
aは後続の文で使うための変数みたいなもので要らなかったら省略しても良いらしい

CREATE (:Person{name:"Alice",From:"Britain"})

さらにラベルも要らなかったら省略してもいいっぽい

CREATE ({name:"Alice",From:"Britain"})

ちなみに無ければ追加,あったら更新をしてくれるMERGEという素敵なものもあるらしい

表示

MATCH(n) RETURN n

とりあえずこれで全部のノードを表示してくれる
MATCH(n)が検索でRETURN nが表示って役割らしい
MATCHだけで実行したらなんか処理しろやって怒られた
カッコいいグラフで表示してくれるのでなんかきもちい
f:id:vayacico:20161127164549p:plain

ノードの検索
MATCH(n) WHERE n.name="Alice" RETURN n

なんとなくSQLっぽい感じかも

MATCH(n) WHERE n.From="Britain" OR n.From="Japan" RETURN n

ORもANDも使える

MATCH (p)-[:friends]->(q) WHERE p.name="Alice"  RETURN q

関係も含めてこんな使い方もできるらしい
パッと見で分かりやすくていいかも
なんでMATCHだけ括弧ついてるのか疑問だったけど()はノードで[]は関係って意味だったみたい

関係の設定
MATCH(p) WHERE p.name="Alice" MATCH(q) WHERE q.name="Karen" CREATE (p)-[:friends]->(q)

これでアリスからカレンへの関係を作成できた
pに検索結果を格納,qに検索結果を格納,p->qの関係を作成って流れだと思う
ちなみにCREATE文はカンマで区切って複数いっぺんに作れるみたい

MATCH(p) WHERE p.name="Alice" MATCH(q) WHERE q.name="Karen" CREATE (p)-[:friends]->(q),(q)-[:friends]->(p)
属性の更新・追加
MATCH(r) WHERE r.name="Alice" SET r.at="Japan"

属性がなければ追加されるらしい

ノードの削除
MATCH(n) WHERE n.name="Alice" DELETE n

検索して削除
わかりやすい
ちなみに関係が存在するノードは消せなくてエラーになる

org.neo4j.kernel.api.exceptions.ConstraintViolationTransactionFailureException: Cannot delete node<553>, because it still has relationships. To delete this node, you must first delete its relationships.

エラーも分かりやすくていい

関係の削除
MATCH(n)-[r]->(p) WHERE n.name="Alice"  DELETE r

関係にも変数を付けられるのでそれを使って削除

感想

思ってたよりかなり分かりやすい
複雑なことをやろうとすると難しいのかもしれないけど