教程目录 引自:https://neo4j.com/docs/getting-started/cypher-intro/patterns-in-practice/
实践中的模式
创建和返回数据
让我们首先看看允许您创建数据的子句。
要添加数据,您只需使用您已经知道的模式。通过提供模式,您可以指定哪些图结构、标签和属性要成为图的一部分。
显然,最简单的子句称为 CREATE
。它创建您指定的模式。
对于您到目前为止所看到的模式,这可能如下所示:
CREATE (:Movie {title: 'The Matrix', released: 1997})
如果您运行此语句,Cypher® 将返回更改的数量:在本例中,添加一个节点、一个标签和两个属性。
Created Nodes: 1
Added Labels: 1
Set Properties: 2
Rows: 0
由于您从一个空数据库开始,因此您现在有一个数据库,其中包含一个节点:
如果您还想返回创建的数据,您可以添加一个 RETURN
子句,该子句引用您已分配给模式元素的变量。
Cypher 中的 RETURN
关键字指定您可能希望从 Cypher 查询返回的值或结果。
您可以告诉 Cypher 返回节点、关系、节点和关系属性或查询结果中的模式。
执行写入过程时不需要 RETURN
,但读取时需要。
当使用 RETURN
时,前面讨论的节点和关系变量变得很重要。
CREATE (p:Person {name: 'Keanu Reeves', born: 1964})
RETURN p
这是返回的内容:
Created Nodes: 1
Added Labels: 1
Set Properties: 2
Rows: 1
+----------------------------------------------+
| p |
+----------------------------------------------+
| (:Person {name: 'Keanu Reeves', born: 1964}) |
+----------------------------------------------+
如果要创建多个元素,可以用逗号分隔元素或使用多个 CREATE
语句。
当然,您还可以创建更复杂的结构,例如包含有关角色的信息的 ACTED_IN
关系,或导演的 DIRECTED
关系。
CREATE (a:Person {name: 'Tom Hanks', born: 1956})-[r:ACTED_IN {roles: ['Forrest']}]->(m:Movie {title: 'Forrest Gump', released: 1994})
CREATE (d:Person {name: 'Robert Zemeckis', born: 1951})-[:DIRECTED]->(m)
RETURN a, d, r, m
这是更新后的图的一部分:
在大多数情况下,您希望将新数据添加到现有结构。这需要知道如何在图数据中查找现有模式,这将在下一节中介绍。
匹配模式
匹配模式是 MATCH
语句的任务。您将到目前为止使用的相同类型的模式传递给 MATCH
,以描述您要查找的内容。它类似于按示例查询,只是您的示例还包括结构。要返回节点、关系、属性或模式,您需要在 MATCH
子句中为要返回的数据指定变量。
MATCH
语句搜索您指定的模式,并为每个成功的模式匹配返回一行。
要查找您到目前为止创建的数据,您可以开始查找所有带有 Movie
标签的节点。
MATCH (m:Movie)
RETURN m
结果如下:
这应该显示《黑客帝国》和《阿甘正传》。
您还可以查找特定的人,例如基努·里维斯。
MATCH (p:Person {name: 'Keanu Reeves'})
RETURN p
此查询返回匹配的节点:
请注意,您只提供足够的信息来查找节点,并非所有属性都是必需的。在大多数情况下,您都有关键属性,例如 SSN、ISBN、电子邮件、登录名、地理位置或产品代码来查找。
您还可以找到更有趣的连接,例如,汤姆·汉克斯出演的电影的标题和他扮演的角色。
MATCH (p:Person {name: 'Tom Hanks'})-[r:ACTED_IN]->(m:Movie)
RETURN m.title, r.roles
Rows: 1
+------------------------------+
| m.title | r.roles |
+------------------------------+
| 'Forrest Gump' | ['Forrest'] |
+------------------------------+
在本例中,您只返回了您感兴趣的节点和关系的属性。您可以通过点表示法 identifier.property
在任何地方访问它们。
当然,这只列出了汤姆·汉克斯在《阿甘正传》中扮演的 Forrest 角色,因为这就是您添加的所有数据。
现在您已经知道足够多的知识来将新节点添加到现有节点,并且可以将 MATCH
和 CREATE
组合起来以将结构附加到图中。
Cypher 示例
让我们看一些使用 MATCH
和 RETURN
关键字的示例。每个后续示例都比前一个示例更复杂。最后两个示例首先解释了我们试图实现的目标。如果您单击每个 Cypher 代码段下方的“运行查询”按钮,您可以在图或表的格式中查看结果。
示例 1:查找图中带有标签 Person
的节点。请注意,如果要检索 RETURN
子句中的节点,则必须为 Person
节点使用一个变量,例如 p
。
MATCH (p:Person)
RETURN p
LIMIT 1
示例 2:查找图中名称为“Tom Hanks”的 Person
节点。请记住,您可以随意命名您的变量,只要您稍后引用相同的名称即可。
MATCH (tom:Person {name: 'Tom Hanks'})
RETURN tom
示例 3:查找汤姆·汉克斯导演的电影。
说明:首先,您应该找到汤姆·汉克斯的 Person
节点,然后找到他连接到的 Movie
节点。为此,您必须从汤姆·汉克斯的 Person
节点到 Movie
节点遵循 DIRECTED
关系。您还指定了 Movie
的标签,以便查询仅查看带有该标签的节点。由于您只关心在此查询中返回电影,因此您需要为该节点提供一个变量(movie
),但不需要为 Person
节点或 DIRECTED
关系提供变量。
MATCH (:Person {name: 'Tom Hanks'})-[:DIRECTED]->(movie:Movie)
RETURN movie
示例 4:查找汤姆·汉克斯导演的电影,但这次只返回电影的标题。
说明:此查询与上一个查询类似。示例 3 返回了整个 Movie
节点及其所有属性。对于此示例,您仍然需要找到汤姆的电影,但现在您只关心它们的标题。您应该使用语法 variable.property
访问节点的 title
属性以返回名称值。
MATCH (:Person {name: 'Tom Hanks'})-[:DIRECTED]->(movie:Movie)
RETURN movie.title
别名返回值
并非所有属性都像上面示例中的 movie.title
那样简单。由于属性长度、多字描述、开发人员术语和其他快捷方式,某些属性的名称很差。这些命名约定可能难以阅读,尤其是在报告和其他面向用户的界面上。
命名不佳的属性
// 命名不佳的属性
MATCH (tom:Person {name:'Tom Hanks'})-[rel:DIRECTED]-(movie:Movie)
RETURN tom.name, tom.born, movie.title, movie.released
就像 SQL 一样,您可以使用 AS
关键字重命名返回结果,并使用更清晰的名称为属性设置别名。
使用别名获得更清晰的结果
// 使用别名获得更清晰的打印结果
MATCH (tom:Person {name:'Tom Hanks'})-[rel:DIRECTED]-(movie:Movie)
RETURN tom.name AS name, tom.born AS `Year Born`, movie.title AS title, movie.released AS `Year Released`
您可以通过在别名前后使用反引号字符来指定包含空格的返回别名(movie.released AS Year Released
)。如果您没有包含空格的别名,则无需使用反引号。
附加结构
要使用新信息扩展图,首先要匹配现有的连接点,然后使用关系将新创建的节点附加到它们。像这样可以为汤姆·汉克斯添加一部新电影《云图》:
MATCH (p:Person {name: 'Tom Hanks'})
CREATE (m:Movie {title: 'Cloud Atlas', released: 2012})
CREATE (p)-[r:ACTED_IN {roles: ['Zachry']}]->(m)
RETURN p, r, m
这是数据库中的结构:
重要的是要记住,您可以为节点和关系分配变量,并在以后使用它们,无论它们是创建的还是匹配的。
可以在单个 CREATE
子句中附加节点和关系。但是,为了提高可读性,将它们分开是有帮助的。
MATCH
和 CREATE
组合的一个棘手方面是,每个匹配的模式都会得到一行。这会导致后续的 CREATE
语句为每一行执行一次。在许多情况下,这正是您想要的。如果不是有意的,请将 CREATE
语句移动到 MATCH
之前,或者使用稍后讨论的方法更改查询的基数,或者使用下一个子句的获取或创建语义:MERGE
。
完成模式
每当您从外部系统获取数据或不确定某些信息是否已存在于图中时,您都希望能够表达可重复(幂等)的更新操作。在 Cypher 中,MERGE
子句具有此功能。它的作用类似于 MATCH
或 CREATE
的组合,它在创建数据之前检查数据是否存在。使用 MERGE
,您可以定义要查找或创建的模式。通常,与 MATCH
一样,您只想在核心模式中包含要查找的关键属性。MERGE
允许您提供要在 ON CREATE
上设置的其他属性。
如果您不知道您的图是否已经包含《云图》,您可以再次合并它。
MERGE (m:Movie {title: 'Cloud Atlas'})
ON CREATE SET m.released = 2012
RETURN m
Created Nodes: 1
Added Labels: 1
Set Properties: 2
Rows: 1
+-------------------------------------------------+
| m |
+-------------------------------------------------+
| (:Movie {title: 'Cloud Atlas', released: 2012}) |
+-------------------------------------------------+
在这两种情况下,您都会得到一个结果:要么是图中已经存在的数据(可能不止一行),要么是一个新创建的 Movie
节点。
没有任何先前分配变量的 MERGE
子句要么匹配完整模式,要么创建完整模式。它永远不会产生模式中匹配和创建的部分混合。要实现部分匹配/创建,请确保对不应受影响的部分使用已定义的变量。
因此,最重要的是,MERGE
确保您不能创建重复的信息或结构,但它需要首先检查现有匹配项的成本。尤其是在大型图上,扫描一组带有标签的节点以查找特定属性可能代价高昂。您可以通过创建支持索引或约束来缓解这种情况,这将在后面的章节中讨论。但这仍然不是免费的,因此,只要您确定不会创建重复数据,请使用 CREATE
而不是 MERGE
。
MERGE
还可以断言仅创建一次关系。为此,您必须从先前的模式匹配中传入两个节点。
MATCH (m:Movie {title: 'Cloud Atlas'})
MATCH (p:Person {name: 'Tom Hanks'})
MERGE (p)-[r:ACTED_IN]->(m)
ON CREATE SET r.roles =['Zachry']
RETURN p, r, m
如果关系的方向是任意的,您可以省略箭头。MERGE
检查任一方向的关系,如果没有匹配的关系,则创建一个新的有向关系。
如果您选择仅从前面的子句中传入一个节点,则 MERGE
提供了一个有趣的功能。它仅在给定模式的提供的节点的直接邻域内匹配,如果未找到该模式,则创建它。这对于创建树结构非常有用。
CREATE (y:Year {year: 2014})
MERGE (y)<-[:IN_YEAR]-(m10:Month {month: 10})
MERGE (y)<-[:IN_YEAR]-(m11:Month {month: 11})
RETURN y, m10, m11
这是创建的图结构:
这里没有对两个 Month
节点进行全局搜索;仅在 2014 Year
节点的上下文中搜索它们。
代码挑战
现在了解了基础知识,请使用下面的部分构建一个 Cypher 语句,以查找汤姆·汉克斯 DIRECTED
的每个 Movie
的标题和发行年份。单击这些部分以按顺序添加它们,完成后,单击“运行查询”以查看您是否正确。您可以单击代码块内的任何查询部分以将其删除。
从下面的选项中选择以完成查询:
{name:})-[:MovieRETURNPerson"Tom Hanks")m.title, m.released]->(m:DIRECTED(p:MATCH