Neo4j ver2以降について書かれたものは以下を参照してください。
Neo4jphpをcomposerを使ってインストールする
composerを使わないでneo4jphpからNeo4jに接続してみた
前回はneo4jphp.pharの設置まででしたので、今回はどういうふうに使うかを紹介します。
サンプルスクリプトを考えるのが面倒なので、実際に使ったものをそのまま載せます。
映画俳優と出演映画の紐付けを例にやってるところがよくありますが、私は泥くさーく人事情報を使います。小さい会社ならエクセルで十分ですが、でっかい企業になるとかなり大変で、特に問題になるのは社員数ではなく部署管理です。部署のツリー構造も階層数が一定ではなく、RDBを使ってもSQLのサブクエリ―では対応できません。
neo4jphp.pharのオブジェクトやメソッドの使い方を紹介するのが目的なので、アルゴリズムは気にしないでください。
このスクリプトが何をやっているのかざっと説明しますと・・・
- 部署数千、社員数万の会社の部署と社員をNeo4Jにインポートするプログラムです。
- オリジナルDBはMySQLで、部署テーブル、社員情報テーブル、社員と部署を紐づける参照テーブルの3つのテーブルがあります。
- プログラムは部署テーブルのツリーを下りながら、それに紐づく社員を取得し、Neo4Jに部署ノードを作り、親ノードと紐づけ、社員ノードを作って、その部署と紐づけていきます。
- 社員の兼務は有りです。2重登録は有りません。
*例内ではボールドになっている部分がneo4jphpに関する部分です。その他は無視してください。
include_once("define.php");
include_once("db.php");
require("/usr/share/php/neo4jphp.phar");// neo4jphp.pharのリクアイア
//ラッパーオブジェクトの生成。ホストとポート番号を指定する。
$neo4j = new Everyman\Neo4j\Client('localhost', 7474);
//ここはツリー構造を下っていくときに使い回すSQLのひな形なので、気にしないでください。
define('_BASIC_SQL_','select id, code, title, parent, sort from sec_organization where parent = ?');
define('_EMP_SQL_', 'select o.id as oid, suo.org_id as org_id, e.id as eid, e.account, e.lastname, e.firstname, e.last_kana,
e.first_kana, e.pass from sec_user as e, sec_user_org as suo, sec_organization as o where e.id = suo.id and suo.org_id = o.id and suo.org_id = ?');
//これはMySQLにコネクションを張ってます。
$db = new dbAccess(_DB_HOST_,_DB_NAME_,_DB_USER_,_DB_PASS_);
//基本、ルートノードはすでに存在していて、ノードID0番を持っていますので、そのIDをキーにオブジェクトを生成します。
//これが第一階層の部署の親ノードになります。
$root = $neo4j->getNode(0);
//下にあるgetOrgという関数に親のノードID,DBのコネクションオブジェクト、Neo4Jのオブジェクト、親ノードのオブジェクトを渡しします。その後再起的に繰り返します。
getOrg(0, $db, $neo4j, $root);
$count = 0;
$db->close();
function getOrg($parent, &$db, &$neo4j, &$upper_org = null, $indent = '') {
global $count;
$count++;
$indent = $indent.' ';
$res = $db->query(_BASIC_SQL_, array($parent));
if (!$res->numRows()) { return; }
while($ROW = $res->fetchRow()) {
$org = $neo4j->makeNode()->save(); //新規のノードを作成し、保存します。
$org->setProperty('type', 'org')//そのノードにプロパティを追加します。ここは'type'というプロパティに'org'という値を設定しています。
->setProperty('name', $ROW['title'])//これは、'name'というプロパティにDBから拾ってきた部署名を設定。
->setProperty('del_flag', 0)->save();//'del_flag'(削除フラグ)に0を設定し、最後に保存しています。
//ここは、もし親階層があったら、その親から、自分に向けて、'HAS'というリレーションを追加して、保存します。
if ($upper_org) {
$upper_org->relateTo($org, 'HAS')->save();
}
print $indent.$ROW['title'].' '.$ROW['id']."\n";
$res2 = $db->query(_EMP_SQL_, array($ROW['id']));
//もし、この部署に社員が登録されていたら、
//社員のノードを作成し、社員属性を登録します。
while($ROW2 = $res2->fetchRow()) {
$emp = $neo4j->makeNode()->save();//新しく社員のノードを追加
$emp->setProperty('account', $ROW2['account'])
->setProperty('lastname', $ROW2['lastname'])
->setProperty('lastname', $ROW2['lastname'])
->setProperty('firstname', $ROW2['firstname'])
->setProperty('last_kana', $ROW2['last_kana'])
->setProperty('first_kana', $ROW2['first_kana'])
->setProperty('pass', $ROW2['pass'])->save();//最後に保存
//社員ノードから、部署へ'BELONG_TO'というリレーションを張る。同時に保存
$emp->relateTo($org, 'BELONG_TO')->save();
print $indent.$indent.'組織:'.$ROW2['org_id'].' ユーザID:'.$ROW2['eid'].' '.$ROW2['lastname']." ".$ROW2['firstname']."\n";
}
$res2->free();
getOrg($ROW['id'], $db,$neo4j,$org,$indent);
}
$res->free();
}
print time()."\n";
exit;
【新しいノード追加】
$n = $neo4j->makeNode()->save();
で作れます。
【プロパティ追加】
この$nに対して、プロパティーは:
$n->setProperty(‘プロパティ名’, ‘値’);
で設定します。
【コミットするには】
$n->save();
です。続けて、$n->setProperty(‘プロパティ名’, ‘値’)->save();でもOKです。
【リレーションの追加】
二つのノードをリレーションで結ぶには、
ノードA->relateTo(ノードB, ‘リレーション名’);
で、親ノードから子ノード向きのリレーションが設定できます。
ここで親・子というのは適切ではなく、階層的にはしたのノードでも上に向けてリレーションを張ることもあります。
上の例では、部署から下層部署へ向けて’HAS’というリレーションを設定していますが、社員から部署へは’BELONG_TO’というリレーションを張っています。
以上は、neo4jphp.pharに組み込まれたノード作成、プロパティ設定、リレーション設定の例です。
今回は新規にできたノードに対しての操作だけですので、次は、ノードIDをもとにノードオブジェクトを生成し、ノードやリレーションの削除、Cypherを使ったクエリーとその結果の取り出しを紹介しようと思います。
