GraphGists

首先,我们导入一些数据以便从中检索结果

CREATE (matrix:Movie {title:"The Matrix",released:1997})
CREATE (cloudAtlas:Movie {title:"Cloud Atlas",released:2012})
CREATE (forrestGump:Movie {title:"Forrest Gump",released:1994})
CREATE (keanu:Person {name:"Keanu Reeves", born:1964})
CREATE (robert:Person {name:"Robert Zemeckis", born:1951})
CREATE (tom:Person {name:"Tom Hanks", born:1956})
CREATE (tom)-[:ACTED_IN {roles:["Forrest"]}]->(forrestGump)
CREATE (tom)-[:ACTED_IN {roles:['Zachry']} ]->(cloudAtlas)
CREATE (robert)-[:DIRECTED]->(forrestGump)

这是我们将要开始使用的数据

Nodes created: 6
Relationships created: 3
Properties set: 14
Labels added: 6

筛选结果

到目前为止,我们已经在图中匹配了模式,并且总是返回所有找到的结果。通常,我们想要看到的结果会有一些条件限制。类似于 SQL,这些筛选条件在 WHERE 子句中表达。这个子句允许使用任意数量的布尔表达式(谓词),并与 ANDORXORNOT 结合使用。最简单的谓词是比较,特别是相等性比较。

MATCH (m:Movie)
WHERE m.title = "The Matrix"
RETURN m

对于一个或多个属性的相等性比较,也可以使用更紧凑的语法

MATCH (m:Movie {title: "The Matrix"})
RETURN m

其他选项包括数值比较、匹配正则表达式以及检查集合中是否存在值。

下面的 WHERE 子句包括一个正则表达式匹配、一个大于比较以及一个测试值是否存在于集合中的检查。

MATCH (p:Person)-[r:ACTED_IN]->(m:Movie)
WHERE p.name =~ "K.+"
   OR m.released > 2000
   OR "Neo" IN r.roles
RETURN p,r,m

可能有点令人惊讶的一个方面是,您甚至可以使用模式作为谓词。MATCH 会扩展匹配模式的数量和形状,而模式谓词会限制当前结果集。它只允许满足附加模式(或 NOT)的路径通过。

MATCH (p:Person)-[:ACTED_IN]->(m)
WHERE NOT (p)-[:DIRECTED]->()
RETURN p,m

在这里,我们查找演员(因为他们具有 ACTED_IN 关系),然后跳过那些曾经 DIRECTED 过任何电影的演员。

还有更高级的筛选方法,例如集合谓词,我们稍后会介绍。

返回结果

到目前为止,我们仅通过标识符直接返回了节点、关系或路径。但 RETURN 子句实际上可以返回任意数量的表达式。那么,在 Cypher 中表达式到底是什么?

最简单的表达式是字面值,例如数字、字符串和数组,如 [1,2,3],以及映射,如 {name:"Tom Hanks", born:1964, movies:["Forrest Gump", …​], count:13}。您可以使用点语法(如 n.name)访问任何节点、关系或映射的单个属性。可以使用下标(如 names[0]movies[1..-1])检索数组的单个元素或切片。每个函数求值(如 length(array)toInt("12")substring("2014-07-01",0,4)coalesce(p.nickname,"n/a"))也是一个表达式。

您在 WHERE 中使用的谓词算作布尔表达式。

当然,简单的表达式可以组合和连接起来形成更复杂的表达式。

默认情况下,表达式本身将用作列的标签,在许多情况下,您希望使用 expression AS alias 为其指定一个更容易理解的别名。稍后,您可以使用该别名引用该列。

MATCH (p:Person)
RETURN p, p.name AS name, upper(p.name), coalesce(p.nickname,"n/a") AS nickname, {name: p.name, label:head(labels(p))} AS person

如果您对唯一结果感兴趣,可以在 RETURN 后面使用 DISTINCT 关键字来指示。

聚合信息

在许多情况下,您希望聚合或分组在遍历图中的模式时遇到的数据。在 Cypher 中,聚合发生在计算最终结果时的 RETURN 子句中。支持许多常见的聚合函数,例如 countsumavgminmax,还有更多。

可以使用以下语句计算数据库中的人数

MATCH (:Person)
RETURN count(*) as people

请注意,在聚合期间会跳过 NULL 值。要仅聚合唯一值,请使用 DISTINCT,例如在 count(DISTINCT role) 中使用。

Cypher 中的聚合就是这样工作的。您指定要聚合的结果列,Cypher 会将所有非聚合列用作分组键

聚合会影响在排序或后续查询部分中仍然可见的数据。

要查明演员和导演合作的频率,您可以运行以下语句

MATCH (actor:Person)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(director:Person)
RETURN actor,director,count(*) as collaborations

通常,您会在聚合 count(x) 后进行排序和分页。

排序和分页

排序的工作方式与其他查询语言类似,使用 ORDER BY expression [ASC|DESC] 子句。表达式可以是前面讨论过的任何表达式,只要它可以从返回的信息中计算出来。

例如,如果您返回 person.name,您仍然可以 ORDER BY person.age,因为两者都可以从 person 引用中访问。您不能根据无法从返回的信息中推断出的内容进行排序。这在聚合和 DISTINCT 返回值时尤其重要,因为它们都会移除聚合数据的可见性。

分页是直接使用 SKIP {offset} LIMIT {count}

一种常见的模式是聚合计数(得分或频率),按其排序并仅返回前 n 个条目。

例如,要找出最多产的演员,您可以这样做

MATCH (a:Person)-[:ACTED_IN]->(m:Movie)
RETURN a,count(*) as appearances
ORDER BY appearances DESC
LIMIT 10;

收集聚合

最有用的聚合函数是 collect,顾名思义,它将所有聚合的值收集到*真实的*数组或列表中。这在许多情况下非常方便,因为在聚合时不会丢失详细信息。

collect 非常适合检索典型的父子结构,其中每行返回一个核心实体(父、根或头),以及使用 collect 创建的相关集合中的所有依赖信息。这意味着无需为每个子行重复父信息,甚至无需运行 1+n 条语句分别检索父及其子。

要检索数据库中每部电影的演职人员,可以使用以下语句

MATCH (m:Movie)<-[:ACTED_IN]-(a:Person)
RETURN m.title as movie, collect(a.name) as cast, count(*) as actors

collect 创建的列表既可以供消费 Cypher 结果的客户端使用,也可以直接在语句中使用任何集合函数或谓词。

© . All rights reserved.