Cypher - 是否可以在合成数据上声明通用 table 表达式?

Cypher - is it possible to declare common table expression over synthetized data?

玩SQL或者解释一些语言特性,往往不需要真实数据库中的数据table,只需要普通的table表达式即可:

with my_sample (id, name, age) as (values
  (1, 'Alice', 17),
  (2, 'Bob', 19)
), can_drive_car (name) as (
  select name from my_sample where age >= 18
)
select * from can_drive_car

Cypher 中是否存在任何等效项?我的意思是即时创建图表,查询它和 return 结果而不影响数据库中的数据。伪代码:

WITH CREATE (:Person {name:'Alice'})-[:FRIEND]->(:Person {name:'Bob'})-[:FRIEND]->(:Person {name:'Charlie'})
MATCH p=shortestPath((a {name:'Alice'})-[*]->(c {name:'Charlie'}))
RETURN p

我知道 Cypher WITH 子句。尽管命名相同,但在我看来,在 Cypher 中 - 与 SQL 不同 - 该子句仅将先前查询部分的结果(在 Neo4j 数据库中的真实图形数据上调用)传递给后续流,AFAIK 它不能伪造任何东西在我的 SQL 示例中。

遗憾的是,我还没有找到任何符合 100% 要求的工具,但有一些工具可以让您在这方面更加灵活:

  1. 虚拟节点和关系

https://neo4j.com/labs/apoc/4.1/virtual/virtual-nodes-rels/。这些是在查询期间存在的节点和 rels。但是,它们仅用于可视化,您不能对它们执行匹配。例如,这个 returns 虚拟节点 & rels:

CALL apoc.create.vNode(['Person'],{name:'Alice'}) yield node as a
CALL apoc.create.vNode(['Person'],{name:'Bob'}) yield node as b
CALL apoc.create.vNode(['Person'],{name:'Charlie'}) yield node as c
CALL apoc.create.vRelationship(a, 'FRIEND', {}, b) yield rel as rel1
CALL apoc.create.vRelationship(b, 'FRIEND', {}, c) yield rel as rel2
RETURN *

但是,一旦您添加了 MATCH 语句,它就returns什么都没有了。

CALL apoc.create.vNode(['Person'],{name:'Alice'}) yield node as a
CALL apoc.create.vNode(['Person'],{name:'Bob'}) yield node as b
CALL apoc.create.vNode(['Person'],{name:'Charlie'}) yield node as c
CALL apoc.create.vRelationship(a, 'FRIEND', {}, b) yield rel as rel1
CALL apoc.create.vRelationship(b, 'FRIEND', {}, c) yield rel as rel2
MATCH p=shortestPath((a)-[*]->(c))
RETURN p
  1. 虚拟资源

https://neo4j.com/labs/apoc/4.1/virtual-resource/ 这是一种在查询 neo4j 节点的同时查询外部数据源的方法。来自外部源的数据不会带入主图中,但您可以对虚拟资源中的节点进行查询。但是,它不符合要求,因为似乎没有一种简单的方法可以做到这一点 self-contained。您需要有一个包含“虚拟”数据的外部资源。它可以像 CSV 文件一样简单,但仍然如此。

  1. 图预测,使用图数据科学库

GDS 库在图形投影上执行操作,而不是数据的 written-to-disk 副本,例如 SQL 中的临时 table。您可以过滤节点和关系以使用较小的数据集。但是,您不能向图形投影添加新节点。

我同意拥有这样的东西会非常有用 - 我希望出现一个!

对于一个快速(和肮脏的)解决方案,我通常通过向我正在创建的节点添加一个额外的测试标签来解决这个问题,例如:

CREATE (:Person:Test {name:'Alice'})-[:WORKS_FOR]->(:Manager:Test {name:'Bob'})-[:DRIVES]->(:Car:Test {name:'Ford Cortina'})

然后,当我完成后 MATCH(x:Test) DETACH DELETE x 清除所有内容。

不理想,但如果您的测试很简单,可能适合您。