luxplus / neo4j-php-client

Neo4j-PHP-Client 是最先进的 Neo4j PHP 客户端

该包的规范仓库似乎已消失,因此该包已被冻结

4.8.5 2018-11-21 12:08 UTC

This package is auto-updated.

Last update: 2022-06-11 10:23:09 UTC


README

Neo4j 企业级客户端

Build Status Latest Stable Version Total Downloads License

介绍

Neo4j-PHP-Client 是最先进且灵活的 Neo4j PHP 客户端。

什么是 Neo4j?

Neo4j 是一个事务性、开源的图数据库。图数据库以连接的数据结构管理数据,能够以非常易访问的方式表示任何类型的数据。信息存储在节点及其连接关系中,这两者都可以具有任意属性。了解更多信息请访问 什么是图数据库?

关键特性

  • 支持多连接
  • 支持 Bolt 二进制协议
  • 内置并自动支持 Neo4j 企业版主从模式,包括自动从节点回退

Neo4j 版本支持

版本 测试
<= 2.2.6
>= 2.2.6
2.2
2.3
3.0 +

Neo4j 特性支持

特性 支持?
认证
远程 Cypher
事务
高可用性
嵌入式 JVM 支持
二进制协议

要求

  • PHP >= 5.6
  • ext-bcmath
  • ext-mbstring
  • Neo4j 数据库(最小版本 2.2.6)

获取帮助

您可以使用以下方式

实现

安装和基本用法

安装

将库添加到您的 composer 依赖项

composer require "graphaware/neo4j-php-client:^4.0"

需要 composer 自动加载器,通过提供连接别名和连接设置来配置您的连接

<?php

require_once 'vendor/autoload.php';

use GraphAware\Neo4j\Client\ClientBuilder;

$client = ClientBuilder::create()
    ->addConnection('default', 'http://neo4j:password@localhost:7474') // Example for HTTP connection configuration (port is optional)
    ->addConnection('bolt', 'bolt://neo4j:password@localhost:7687') // Example for BOLT connection configuration (port is optional)
    ->build();

现在您已准备好连接到数据库。

注意:构建方法将处理配置设置并返回一个 Client 实例。

基本用法

发送 Cypher 查询

$client->run('CREATE (n:Person)');

带参数的 Cypher 查询

$client->run('CREATE (n:Person) SET n += {infos}', ['infos' => ['name' => 'Ales', 'age' => 34]]);

读取结果

$result = $client->run('MATCH (n:Person) RETURN n');
// a result always contains a collection (array) of Record objects

// get all records
$records = $result->getRecords();

// get the first or (if expected only one) the only record

$record = $result->getRecord();

Record 对象包含 Cypher 查询中的一条记录的值

$query = 'MATCH (n:Person)-[:FOLLOWS]->(friend) RETURN n.name, collect(friend) as friends';
$result = $client->run($query);

foreach ($result->getRecords() as $record) {
    echo sprintf('Person name is : %s and has %d number of friends', $record->value('name'), count($record->value('friends')));
}

Cypher 语句和栈

理想情况下,您应该将语句堆叠起来,一次发布它们以提高性能。

您可以创建作为袋的 Cypher 语句栈,并使用客户端运行此栈,例如

$stack = $client->stack();

$stack->push('CREATE (n:Person {uuid: {uuid} })', ['uuid' => '123-fff']);
$stack->push('MATCH (n:Person {uuid: {uuid1} }), (n2:Person {uuid: {uuid2} }) MERGE (n)-[:FOLLOWS]->(n2)', ['uuid1' => '123-fff', 'uuid2' => '456-ddd']);

$results = $client->runStack($stack);

标记您的 Cypher 语句

有时,您可能想从堆栈中检索特定结果,一个简单的方法是为您的 Cypher 语句标记。

标记通过 runpush 方法的第三个参数传递

$stack = $client->stack();

$stack->push('CREATE (n:Person {uuid: {uuid} })', ['uuid' => '123-fff'], 'user_create');
$stack->push('MATCH (n:Person {uuid: {uuid1} }), (n2:Person {uuid: {uuid2} }) MERGE (n)-[r:FOLLOWS]->(n2) RETURN id(r) as relId', ['uuid1' => '123-fff', 'uuid2' => '456-ddd'], 'user_follows');

$results = $client->runStack($stack);

$followResult = $results->get('user_follows');
$followRelationshipId = $followResult->getRecord()->value('relId');

处理结果集

基础

run 方法返回单个 Result 对象。其他方法可以返回多个结果,返回的 ResultCollection 对象是可遍历的。

Result 对象包含语句的 recordssummary,API 中提供了以下方法:

$result->firstRecord(); // Returns the first record of the Statement Result

$result->records(); // Returns all records

$result->summarize(); // Returns the ResultSummary

摘要

ResultSummary 包含 Statement、统计信息和可用的 QueryPlan

$summary = $result->summarize();

$query = $summary->statement()->text();

$stats = $summary->updateStatistics();

$nodesUpdated = $stats->nodesUpdated();
$propertiesSet = $stats->propertiesSet();

// Does the statement affected the graph ?
$affected = $stats->containsUpdates();

记录值

每个记录包含 Cypher 查询返回的一行值


$query = 'MATCH (n:Person) n, n.name as name, n.age as age';
$result = $client->run($query);

foreach ($result->records() as $record) {
    print_r($record->get('n')); // nodes returned are automatically hydrated to Node objects

    echo $record->value('name') . PHP_EOL;
    echo $record->value('age') . PHP_EOL;
}

客户端负责将图对象水分解为 PHP 对象,因此适用于节点、关系和路径

节点
  • labels() : 返回标签数组(字符串)
  • identity() : 返回节点的内部 ID
  • values() : 返回节点的属性(数组)
  • value($key) : 返回给定属性键的值
  • hasValue($key) : 返回节点是否具有给定键的属性
  • keys() : 返回表示节点属性键的数组
  • hasLabel($label) : 返回节点是否具有给定的标签(布尔值)
关系
  • type() : 返回关系类型
  • identity() : 返回关系的内部 ID
  • values() : 返回关系的属性(数组)
  • value($key) : 返回给定属性键的值
  • hasValue($key) : 返回关系是否具有给定键的属性
  • keys() : 返回表示关系属性键的数组
  • startNodeIdentity : 返回起始节点 ID
  • endNodeIdentity : 返回结束节点 ID
路径
  • start() : 返回路径的起始节点
  • end() : 返回路径的结束节点
  • length() : 返回路径的长度
  • nodes() : 返回路径中的所有节点
  • relationships : 返回路径中的所有关系

处理结果(从v3到v4)

关于这个主题有3个主要概念

  1. a 结果
  2. a 记录
  3. a 记录值

让我们看看一个在浏览器中执行的查询,它包含多种类型

MATCH (n:Address)
RETURN n.address as addr, n, collect(id(n)) as ids
LIMIT 5

screen shot 2016-05-11 at 20 54 34bis

结果

结果 是一组 记录 对象,你在浏览器中看到的每一行都是一个 记录,它包含 记录值

  • 蓝色为结果
  • 橙色为记录
  • 绿色为记录值
记录

与之前的客户端版本相比,不再自动将所有记录合并为一个大的记录,因此您需要迭代 结果 中的所有记录

$query = 'MATCH (n:Address)
RETURN n.address as addr, n, collect(id(n)) as ids
LIMIT 5';
$result = $client->run($query);

foreach ($result->records() as $record) {
  // here we do what we want with one record (one row in the browser result)
  print_r($record);
}
记录值

每个记录都包含一个 记录值 的集合,这些值由一个 标识,键是您在 Cypher 查询的 RETURN 子句中给出的标识符。在我们的示例中,一个 记录 将包含以下键

  • addr
  • n
  • ids

为了访问值,您可以在 记录 对象上使用 get() 方法

$address = $record->get('addr');

值的类型取决于您从 Neo4j 返回的内容,在我们的情况下,将返回以下值

  • 对于 addr 值是一个 字符串
  • 对于 n 值是一个 节点
  • 对于 ids 值是一个 整数 数组

这意味着

$record->get('addr'); // returns a string
$record->get('n'); // returns a Node object
$record->get('ids'); // returns an array

节点关系路径 对象有进一步的方法,因此如果您知道由标识符 n 返回的节点具有 countries 属性,您可以像这样访问它

$addressNode = $record->get('n');
$countries = $addressNode->value('countries');

记录 对象包含三个用于 IDE 便利性的方法,即

$record->nodeValue('n');
$record->relationshipValue('r');
$record->pathValue('p');

这并不提供额外的功能,只是 docblocks 为 IDE 提供自动补全的提示。

额外:结果集合

当您使用 Stack 对象一次性发送多个语句时,它将返回一个包含多个 结果结果集合 对象。因此,在访问记录之前,您需要遍历结果。

使用事务

客户端提供了一个事务对象,可以简化您的事务操作。

创建一个事务

$tx = $client->transaction();

在这个阶段,尚未向服务器发送任何内容(尚未发送 BEGIN 语句),这允许在提交之前堆叠查询或 Stack 对象。

堆叠一个查询

$tx->push('CREATE (n:Person) RETURN id(n)');

同样,到目前为止还没有发送任何内容。

在事务中运行一个查询

有时您想在事务内立即获取一个语句的结果,这可以通过 run 方法完成

$result = $tx->run('CREATE (n:Person) SET n.name = {name} RETURN id(n)', ['name' => 'Michal']);

echo $result->getRecord()->value("id(n)");

如果事务尚未开始,事务的 BEGIN 将会自动完成。

您也可以推送或运行 Stack

$stack = $client->stack();
$stack->push('CREATE (n:Person {uuid: {uuid} })', ['uuid' => '123-fff']);
$stack->push('MATCH (n:Person {uuid: {uuid1} }), (n2:Person {uuid: {uuid2} }) MERGE (n)-[:FOLLOWS]->(n2)', ['uuid1' => '123-fff', 'uuid2' => '456-ddd']);

$tx->pushStack($stack);
// or
$results = $tx->runStack($stack);

提交和回滚

如果您在事务中排了语句(使用push方法添加的),并且完成了工作,您可以提交事务并获取结果。

$stack = $client->stack();
$stack->push('CREATE (n:Person {uuid: {uuid} })', ['uuid' => '123-fff']);
$stack->push('MATCH (n:Person {uuid: {uuid1} }), (n2:Person {uuid: {uuid2} }) MERGE (n)-[:FOLLOWS]->(n2)', ['uuid1' => '123-fff', 'uuid2' => '456-ddd']);

$tx->pushStack($stack);
$tx->pushQuery('MATCH (n) RETURN count(n)');

$results = $tx->commit();

提交后,您将无法在此事务中pushrun语句。

使用多个连接

一般来说,您最好使用HAProxy在集群环境中运行Neo4j。然而,有时您可能需要完全控制将语句发送到哪个实例。

假设有一个包含3个Neo4j节点的环境。

$client = ClientBuilder::create()
    ->addConnection('node1', 'bolt://10.0.0.1')
    ->addConnection('node2', 'bolt://10.0.0.2')
    ->addConnection('node3', 'bolt://10.0.0.3')
    ->setMaster('node1')
    ->build();

默认情况下,$client->run()命令将您的Cypher语句发送到列表中注册的第一个连接。

您可以通过指定别名作为run参数的第四个参数来指定要将语句发送到哪个连接。

$result = $client->run('CREATE (n) RETURN n', null, null, 'node1');

客户端也了解手动配置的主连接,因此使用以下方式发送写操作会更简单。

$client->runWrite('CREATE (n:User {login: 123})');

辅助方法

$client->getLabels();

返回一个Label对象的数组。

事件分发

run方法期间分发3种类型的事件。

  • PreRunEvent:在执行语句或堆栈之前。
  • PostRunEvent:在执行语句或堆栈之后。
  • FailureEvent:在发生失败时,您可以使用此事件禁用客户端抛出异常。
注册监听器

示例

$client = ClientBuilder::create()
    ->addConnection('default', 'bolt://')
    ->registerEventListener(Neo4jClientEvents::NEO4J_PRE_RUN, array($listener, 'onPreRun')
    ->build();

事件分发器可以通过客户端的$client->getEventDispatcher方法获取。

设置

超时(已弃用)

您可以为连接配置全局超时。

$client = ClientBuilder::create()
    ->addConnection('default', 'https://:7474')
    ->setDefaultTimeout(3)
    ->build();

默认的超时时间为5秒。

此功能已弃用,将在版本5中删除。请参阅以下HTTP客户端设置。

TLS

您可以在建立连接时传递一个Configuration实例以启用Bolt协议的TLS加密,以下是一个简单的示例。

$config = \GraphAware\Bolt\Configuration::newInstance()
    ->withCredentials('bolttest', 'L7n7SfTSj')
    ->withTLSMode(\GraphAware\Bolt\Configuration::TLSMODE_REQUIRED);

$client = ClientBuilder::create()
    ->addConnection('default', 'bolt://hodccomjfkgdenl.dbs.gdb.com:24786', config)
    ->build();

HTTP客户端设置

我们使用HTTPlug为您提供对HTTP客户端的完全控制。Neo4jClient的版本4默认使用Guzzle6以保持向后兼容。版本5将为您提供选择所需客户端的选项。有关HTTPlug的更多信息,请参阅他们的文档在这里

要配置您的客户端,您可以将其添加到Configuration。下面是一个使用php-http/curl-client的示例。

use Http\Client\Curl\Client;

$options = [
    CURLOPT_CONNECTTIMEOUT => 3, // The number of seconds to wait while trying to connect.
    CURLOPT_SSL_VERIFYPEER => false // Stop cURL from verifying the peer's certificate
];
$httpClient = new Client(null, null, $options);

$config = \GraphAware\Neo4j\Client\HttpDriver\Configuration::create($httpClient);
$client = ClientBuilder::create()
    ->addConnection('default', 'http://neo4j:password@localhost:7474', $config)
    ->build();

许可

此库根据MIT许可证发布,请参阅与此包捆绑的LICENSE文件。