获取您想要的结果
首先,我们导入一些数据以便从中检索结果
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
子句中表达。这个子句允许使用任意数量的布尔表达式(谓词),并与 AND
、OR
、XOR
和 NOT
结合使用。最简单的谓词是比较,特别是相等性比较。
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
子句中。支持许多常见的聚合函数,例如 count
、sum
、avg
、min
和 max
,还有更多。
可以使用以下语句计算数据库中的人数
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 结果的客户端使用,也可以直接在语句中使用任何集合函数或谓词。
此页面有帮助吗?