如何在 Cypher 中表达以下内容
“返回至少有一个类型 A 的传入边且无传出边的所有节点”。
您可以使用模式从结果子集中排除节点,如下所示:
MATCH ()-[:A]->(n) WHERE NOT (n)-->() RETURN n
尝试
MATCH (n)
WHERE ()-[:A]->n AND NOT n-->()
RETURN n
或
MATCH ()-[:A]->(n)
WHERE NOT n-->()
RETURN DISTINCT n
编辑
模式表达式既可用于模式匹配,也可用作过滤的谓词。如果在
MATCH
子句中使用,则响应该模式的路径将包含在结果中。如果用于过滤,在 WHERE
子句中,该模式将充当先前已匹配的路径的限制条件。结果是有限的,没有扩展到包括过滤条件。当模式用作过滤的谓词时,该谓词的否定也是可以用作过滤条件的谓词。没有路径可以回答模式的否定(如果有这样的事情),因此模式的否定不能在 MATCH
子句中使用。这句话
返回至少有一个类型 A 的传入边并且没有传出边的所有节点
涉及节点
n
上的两种模式,即any incoming relationship [:A] on n
和any outgoing relationship on n
。第二个必须解释为谓词过滤条件的模式,因为它涉及否定 not any outgoing relationship on n
。然而,第一个可以解释为与 n
一起匹配的模式,也可以解释为另一个模式谓词过滤条件。
这两种解释引起了上面的两个密码查询。第一个查询匹配所有节点并使用两种模式来过滤结果。第二个匹配
n
上的传入关系以及 n
并使用第二个模式来过滤结果。
在过滤发生之前,第一个查询只会与每个节点匹配一次。因此,它将为每个符合条件的节点返回一个结果项。第二个查询将为每个路径匹配模式
any incoming relationship [:A] on n
一次,即为 n
上的每个传入关系匹配一次。因此,它可能在结果中多次包含一个节点,因此使用 DISTINCT
关键字来删除双精度数。
如果感兴趣的项目恰好是节点,那么在
WHERE
子句中使用两种模式作为谓词在我看来是正确的解释。它也更高效,因为它只需要在 [:A]
上找到零个或一个传入 n
来解析谓词。如果传入关系也令人感兴趣,那么第二个查询的某些版本是正确的选择。人们需要绑定关系并用它做一些有用的事情,例如返回它。
以下是在“新鲜”neo4j 控制台上执行的两个查询的执行计划。
First query:
----
Filter
|
+AllNodes
+----------+------+--------+-------------+------------------------------------------------------------------------------------------------------------------------------+
| Operator | Rows | DbHits | Identifiers | Other |
+----------+------+--------+-------------+------------------------------------------------------------------------------------------------------------------------------+
| Filter | 0 | 0 | | (nonEmpty(PathExpression((17)-[ UNNAMED18:A]->(n), true)) AND NOT(nonEmpty(PathExpression((n)-[ UNNAMED36]->(40), true)))) |
| AllNodes | 6 | 7 | n, n | |
+----------+------+--------+-------------+------------------------------------------------------------------------------------------------------------------------------+
Second query:
----
Distinct
|
+Filter
|
+TraversalMatcher
+------------------+------+--------+-------------+--------------------------------------------------------------+
| Operator | Rows | DbHits | Identifiers | Other |
+------------------+------+--------+-------------+--------------------------------------------------------------+
| Distinct | 0 | 0 | | |
| Filter | 0 | 0 | | NOT(nonEmpty(PathExpression((n)-[ UNNAMED30]->(34), true))) |
| TraversalMatcher | 0 | 13 | | n, UNNAMED8, n |
+------------------+------+--------+-------------+--------------------------------------------------------------+