Neo4jPHPを使ってCypherのクエリの書き方と結果の取り出し方

Facebooktwitter

始めたばっかりはいまいち分かりづらかった、Neo4jPHPを使ったCypherのクエリの書き方と、結果の取り出し方も、最近やっと見えてきた。
これからいっぱいお世話になると思うので、まとめておこう。

Cypherでクエリを書くときに、期待する結果を指定する方法は大きく2通りある。(と、自分では理解している)
一つは、該当するノードを丸ごと受け取れるようにし、そのノードから値を取り出す方法、もう一つは、プロパティーの名前を指定して、その値を直接取り出す方法。

前者は例えば、親ノードpとリレーションhasでつながったノードID165を持つ子ノードnを取り出そうとしたとき、親ノードも子ノードも同じタイプで、両方ともnameとcodeというプロパティをもつこととすると、それらを取り出すCypherは:

MATCH (p)-[:has]->(n) WHERE id(n)=165 RETURN n, p

この結果を$resultに返したとき、それぞれのプロパティーは以下のように取り出せます。

親ノードのノードIDは$result[0][‘p’]->getId()
親ノードのnameは$result[0][‘p’]->getProperty(‘name’)
親ノードのcodeは$result[0][‘p’]->getProperty(‘code’)

子ノードのノードIDは$result[0][‘n’]->getId()
子ノードのnameは$result[0][‘n’]->getProperty(‘name’)
子ノードのcodeは$result[0][‘n’]->getProperty(‘code’)

ここで、$result配列の0番目のを指定してるのは、結果セットが一つしか返ってこないという前提です。

これをPHPのソースで書くと、

require('vendor/autoload.php');
$client = new Everyman\Neo4j\Client();
$client->getTransport()->setAuth('username', 'password');

$str = "match (p)-[:has]->(n) where id(n)=156 return n, p";
$query = new Everyman\Neo4j\Cypher\Query($client, $str);
$result = $query->getResultSet();
$child_id = $result[0]['n']->getId();
$child_name = $result[0]['n']->getProperty('name');
$child_code = $result[0]['n']->getProperty('code');
$parent_id =  $result[0]['p']->getId();
$parent_name =  $result[0]['p']->getProperty('name');
$parent_code =  $result[0]['p']->getProperty('code');

ここで、結果が複数あるクエリを発行したときの結果の取り出しはこうなります。$resultをforaechでまわして、

foreach ($result as $row) {
    $child_id = $row['n']->getId();
    $child_name = $row['n']->getProperty('name');
    $child_code = $row['n']->getProperty('code');
    $parent_id = $row['p']->getId();
    $parent_name =  $row['p']->getProperty('name');
    $parent_code =  $row['p']->getProperty('code');
}

こんな感じです。

次に、ノードでなく、プロパティーを直接取り出す方法では、上と同じ例を使うと以下のようChpherになります。

MATCH (p)-[:has]->(n) WHERE id(n)=165 RETURN n.name as child_name, n.code as child_code, id(n) as child_id, p.name as parent_name, p.code as parent_code, id(p) as parent_id

この結果が$resultにセットされるとすると、

親ノードのノードIDは$result[0][‘parent_id’]
親ノードのnameは$result[0][‘parent_name’]
親ノードのcodeは$result[0][‘parent_code’]

子ノードのノードIDは$result[0][‘child_id’]
子ノードのnameは$result[0][‘child_name’]
子ノードのcodeは$result[0][‘child_code’]

PHPでは

require('vendor/autoload.php');
$client = new Everyman\Neo4j\Client();
$client->getTransport()->setAuth('username', 'password');

$str = "MATCH (p)-[:has]->(n) WHERE id(n)=165 
    RETURN id(n) as child_id, n.name as child_name, n.code as child_code, 
    id(p) as parent_id, p.name as parent_name, p.code as parent_code";
$query = new Everyman\Neo4j\Cypher\Query($client, $str);
$result = $query->getResultSet();
$child_id = $result[0]['child_id'];
$child_name = $result[0]['child_name'];
$child_code = $result[0]['child_node'];
$parent_id =  $result[0]['parent_id'];
$parent_name =  $result[0]['parent_name'];
$parent_code =  $result[0]['parent_code'];

となります。

どちらを使うかは、プロパティの数とかソースを書くときの効率を考えて使い分ければいいと思います。

ちなみにこの二つの方法は併用が可能です。

MATCH (p)-[:has]->(n) WHERE id(n)=165 RETURN n, id(p) as parent

とすれば、
子ノードのnameは$result[0][‘n’]->getProperty(‘name’)
子ノードのcodeは$result[0][‘n’]->getProperty(‘code’)
親ノードのノードIDは$result[0][‘parent’]

となります。

要するに、CypherのRETURNでノードを返すのか、値を返すのかって違いだけですね。