我们正在使用 php-cypher-dsl 库将 Neo4j cypher 查询转换为 PHP cypher DSL(域特定语言),以获得更大的灵活性。
我们为此苦苦挣扎,因为该库的文档并没有真正详细地解释如何使用它。假设我们在 cypher Neo4j 中有一个简单的查询:
MATCH (a:Resource), (b:Resource)
WHERE a.uri = $uri AND b.uri = $object
CREATE (a)-[r:{$propertyUri}]->(b)
RETURN type(r)
我们如何将这个 Neo4j cypher 查询转换为 PHP cypher DSL?
您需要做的第一件事是创建您想要匹配的所有节点,以及您想要使用的参数,如下所示:
$a = node("Resource"); // (a:Resource)
$b = node("Resource"); // (b:Resource)
$uri = parameter("uri"); // $uri
$object = parameter("object"); // $object
node
函数将节点的标签作为其唯一参数,而parameter
函数将参数名称作为其唯一参数。接下来,您可以开始编写查询。您可以使用 query
函数启动新查询,如下所示:
$query = query();
这会返回一个
Query
对象,该对象有许多方法可以向查询添加新子句,例如 match
、set
、where
和 create
。这些对应于 Cypher 提供的条款。
我们首先匹配节点
$a
和 $b
:
$query = query() // Start a new query
->match([$a, $b]) // Match on both "a" and "b"
...
接下来,我们要创建匹配条件。 php-cypher-dsl 附带了用于创建此类表达式的构建器模式:
...
->where($a->property("uri")->equals($uri)->and($b->property("uri")->equals($object))
...
接下来,在创建
CREATE
子句之前,我们需要创建一个新变量 $r
,该变量在 CREATE
和 RETURN
子句之间共享:
$r = variable(); // Create a new variable
要创建
CREATE
子句,我们需要执行一些技巧来再次从节点中删除 :Resource
标签。这部分API还需要一些改进。我们可以使用 node()->withVariable($a->getVariable())
获得具有相同变量的新节点。总而言之,看起来像:
...
->create(node()->withVariable($a->getVariable())->relationshipTo(node()->withVariable($b->getVariable()), type: $propertyUri, name: $r))
...
最后我们就可以返回我们想要的值了:
...
->returning(Procedure::raw('type', $r)) // The "type" function is not implemented natively, so we use raw
->toQuery(); // Convert the query to a string
所有放在一起,代码如下所示:
use WikibaseSolutions\CypherDSL\Expressions\Procedures\Procedure;
use function WikibaseSolutions\CypherDSL\node;
use function WikibaseSolutions\CypherDSL\parameter;
use function WikibaseSolutions\CypherDSL\query;
use function WikibaseSolutions\CypherDSL\variable;
$propertyUri = "http://example.com";
$a = node("Resource");
$b = node("Resource");
$uri = parameter("uri");
$object = parameter("object");
$r = variable();
$query = query()
->match([$a, $b])
->where($a->property("uri")->equals($uri)->and($b->property("uri")->equals($object)))
->create(node()->withVariable($a->getVariable())->relationshipTo(node()->withVariable($b->getVariable()), type: $propertyUri, name: $r))
->returning(Procedure::raw('type', $r))
->toQuery();
我认为这比使用带变量的普通查询可读性要差得多。如果您不需要复杂的逻辑来构建查询(并且仅使用预先创建的查询,例如您问题中的查询),我建议您不要使用此库。