获取您想要的结果
首先让我们获取一些数据来检索结果
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 结果的客户端使用,也可以直接在语句中使用任何集合函数或谓词。
此页面是否有帮助?