精华 Neo4j官方教程:第12节,编写大型语句
发布于 4 天前 作者 pangguoming 38 次浏览 来自 分享

教程目录 引自:https://neo4j.com/docs/getting-started/cypher-intro/large-statements/

编写大型语句

示例图

我们继续使用与之前相同的示例数据:

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)

这是生成的图: image (插入图表链接)

图 1. 电影图

UNION

如果要组合具有相同结果结构的两个语句的结果,可以使用 UNION [ALL]

例如,以下查询列出了演员和导演:

MATCH (actor:Person)-[r:ACTED_IN]->(movie:Movie)
RETURN actor.name AS name, type(r) AS type, movie.title AS title
UNION
MATCH (director:Person)-[r:DIRECTED]->(movie:Movie)
RETURN director.name AS name, type(r) AS type, movie.title AS title
Rows: 3

+-------------------------------------------------+
| name              | type       | title          |
+-------------------------------------------------+
| 'Tom Hanks'       | 'ACTED_IN' | 'Cloud Atlas'  |
| 'Tom Hanks'       | 'ACTED_IN' | 'Forrest Gump' |
| 'Robert Zemeckis' | 'DIRECTED' | 'Forrest Gump' |
+-------------------------------------------------+

请注意,返回的列必须在所有子句中以相同的方式设置别名。

上面的查询等效于这个更紧凑的查询:

MATCH (actor:Person)-[r:ACTED_IN|DIRECTED]->(movie:Movie)
RETURN actor.name AS name, type(r) AS type, movie.title AS title

WITH

在 Cypher® 中,您可以将语句片段链接在一起,类似于在数据流管道中完成的方式。每个片段都处理前一个片段的输出,并且其结果可以馈送到下一个片段中。只有在 WITH 子句中声明的列才在后续查询部分中可用。

WITH 子句用于组合各个部分并声明数据从一个部分流向另一个部分。WITH 类似于 RETURN 子句。不同之处在于 WITH 子句不会完成查询,而是为下一部分准备输入。表达式、聚合、排序和分页可以以与 RETURN 子句相同的方式使用。唯一的区别是所有列都必须设置别名。

在以下示例中,收集某人出演的电影,然后过滤掉仅出现在一部电影中的电影。

MATCH (person:Person)-[:ACTED_IN]->(m:Movie)
WITH person, count(*) AS appearances, collect(m.title) AS movies
WHERE appearances > 1
RETURN person.name, appearances, movies
Rows: 1

+-------------------------------------------------------------+
| person.name | appearances | movies                          |
+-------------------------------------------------------------+
| 'Tom Hanks' | 2           | ['Cloud Atlas', 'Forrest Gump'] |
+-------------------------------------------------------------+

使用 WITH 子句,您可以将值从查询的一部分传递到另一部分。这允许您在查询中执行一些中间计算或操作以供以后使用。

以下数据集用于演示下面的示例: image (插入图表链接)

图 2. 图:人员、他们喜欢的技术以及他们工作的公司

要重现该图,请运行 Cypher 代码:

CREATE (diana:Person {name: "Diana"})
CREATE (melissa:Person {name: "Melissa", twitter: "@melissa"})
CREATE (dan:Person {name: "Dan", twitter: "@dan", yearsExperience: 6})
CREATE (sally:Person {name: "Sally", yearsExperience: 4})
CREATE (john:Person {name: "John", twitter: "@jennifer", yearsExperience: 5})
CREATE (joe:Person {name: "Joe"})
CREATE (mark:Person {name: "Mark", twitter: "@mark"})
CREATE (ann:Person {name: "Ann"})
CREATE (xyz:Company {name: "XYZ"})
CREATE (x:Company {name: "Company X"})
CREATE (a:Company {name: "Company A"})
CREATE (Neo4j:Company {name: "Neo4j"})
CREATE (abc:Company {name: "ABC"})
CREATE (query:Technology {type: "Query Languages"})
CREATE (etl:Technology {type: "Data ETL"})
CREATE (integrations:Technology {type: "Integrations"})
CREATE (graphs:Technology {type: "Graphs"})
CREATE (dev:Technology {type: "Application Development"})
CREATE (java:Technology {type: "Java"})
CREATE (diana)-[:LIKES]->(query)
CREATE (melissa)-[:LIKES]->(query)
CREATE (dan)-[:LIKES]->(etl)<-[:LIKES]-(melissa)
CREATE (xyz)<-[:WORKS_FOR]-(sally)-[:LIKES]->(integrations)<-[:LIKES]-(dan)
CREATE (sally)<-[:IS_FRIENDS_WITH]-(john)-[:LIKES]->(java)
CREATE (john)<-[:IS_FRIENDS_WITH]-(jennifer)-[:LIKES]->(java)
CREATE (john)-[:WORKS_FOR]->(xyz)
CREATE (sally)<-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]->(melissa)
CREATE (joe)-[:LIKES]->(query)
CREATE (x)<-[:WORKS_FOR]-(diana)<-[:IS_FRIENDS_WITH]-(joe)-[:IS_FRIENDS_WITH]->(mark)-[:LIKES]->(graphs)<-[:LIKES]-(jennifer)-[:WORKS_FOR]->(Neo4j)
CREATE (ann)<-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]->(mark)
CREATE (john)-[:LIKES]->(dev)<-[:LIKES]-(ann)-[:IS_FRIENDS_WITH]->(dan)-[:WORKS_FOR]->(abc)
CREATE (ann)-[:WORKS_FOR]->(abc)
CREATE (a)<-[:WORKS_FOR]-(melissa)-[:LIKES]->(graphs)<-[:LIKES]-(diana)

您必须在 WITH 子句中指定您以后要使用的变量。只有这些变量会传递到查询的下一部分。有多种方法可以使用此功能(例如,计数、收集、过滤、限制结果)。

有关如何使用 WITH 的更多信息,请参阅 Cypher 手册部分。

//Query1: find and list the technologies people like
MATCH (a:Person)-[r:LIKES]-(t:Technology)
WITH a.name AS name, collect(t.type) AS technologies
RETURN name, technologies;

Query1 结果:

Rows: 9

+----------------------------------------------------------+
| name        | technologies                               |
+----------------------------------------------------------+
| 'Sally'     | ['Integrations']                           |
| 'Dan'       | ['Data ETL', 'Integrations']               |
| 'John'      | ['Java', 'Application Development']        |
| 'Diana'     | ['Query Languages', 'Graphs']              |
| 'Jennifer'  | ['Java', 'Graphs']                         |
| 'Ann'       | ['Application Development']                |
| 'Mark'      | ['Graphs']                                 |
| 'Joe'       | ['Query Languages']                        |
| 'Melissa'   | ['Query Languages', 'Data ETL', 'Graphs']  |
+----------------------------------------------------------+
//Query2: find number of friends who have other friends
MATCH (p:Person)-[:IS_FRIENDS_WITH]->(friend:Person)
WITH p, collect(friend.name) AS friendsList, count{(friend)-[:IS_FRIENDS_WITH]-(:Person)} AS numberOfFoFs
WHERE numberOfFoFs > 1
RETURN p.name, friendsList, numberOfFoFs;

Query2 结果:

Rows: 3

+---------------------------------------------------+-----------------+
| p.name        | friendList                        | numberOfFoFs    |
+---------------------------------------------------+-----------------+
| 'Joe'         | ['Mark']                          | 2               |
| 'Jennifer'    | ['Sally', 'John', 'Ann', 'Mark']  | 2               |
| 'John'        | ['Sally']                         | 2               |
+---------------------------------------------------+-----------------+

在第一个查询中,传递了人员姓名和收集的技术类型列表。因此,只有这些项目可以在 RETURN 子句中引用。关系 ® 和人员出生日期都不能使用,因为这些值没有传递。

在第二个查询中,只能引用 p 及其任何属性(姓名、出生日期、工作年限、Twitter)、朋友的集合(作为一个整体,而不是每个值)以及朋友的朋友的数量。由于这些值已在 WITH 子句中传递,因此可以在 WHERERETURN 子句中使用它们。

WITH 要求传递的所有值都具有变量(如果它们还没有变量)。Person 节点在 MATCH 子句中被赋予变量 §,因此不需要在那里分配变量。

WITH 对于在查询之前设置参数也非常有用。在导入数据时,通常对参数键、URL 字符串和其他查询变量很有用。

//Find people with 2-6 years of experience
WITH 2 AS experienceMin, 6 AS experienceMax
MATCH (p:Person)
WHERE experienceMin <= p.yearsExperience <= experienceMax
RETURN p
回到顶部