实践中的模式

创建和返回数据

让我们先看看允许您创建数据的子句。

要添加数据,您只需使用已知的模式。通过提供模式,您可以指定要作为图的一部分的图结构、标签和属性。

显然,最简单的子句称为 CREATE。它创建您指定的模式。

对于您到目前为止查看过的模式,这可能看起来像以下内容

CREATE (:Movie {title: 'The Matrix', released: 1997})

如果您运行此语句,Cypher® 将返回更改次数:在这种情况下,添加一个节点、一个标签和两个属性。

Created Nodes: 1
Added Labels: 1
Set Properties: 2
Rows: 0

由于您从空数据库开始,现在您有一个包含单个节点的数据库

cypher intro patterns in practice01 arr

如果您还想返回创建的数据,您可以添加一个 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

这是更新图的这部分

cypher intro patterns in practice02 arr

在大多数情况下,您希望将新数据添加到现有结构中。这需要了解如何在图数据中查找现有模式,这将在下一节中介绍。

匹配模式

匹配模式是 MATCH 语句的任务。您将到目前为止使用的相同类型的模式传递给 MATCH 来描述您要查找的内容。它类似于按示例查询,只是您的示例还包括结构。要调回节点、关系、属性或模式,您需要在 MATCH 子句中为要返回的数据指定变量。

MATCH 语句搜索您指定的模式,并为每个成功匹配的模式返回一行

要查找您到目前为止创建的数据,您可以开始查找所有标记为 Movie 标签的节点。

MATCH (m:Movie)
RETURN m

这是结果

cypher intro patterns in practice03 arr

这应该显示黑客帝国阿甘正传

您还可以查找特定的人,例如基努·里维斯

MATCH (p:Person {name: 'Keanu Reeves'})
RETURN p

此查询返回匹配的节点

cypher intro patterns in practice04 arr

请注意,您只提供了足够的信息来查找节点,并不需要所有属性。在大多数情况下,您拥有要查找的关键属性,例如 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'] |
+------------------------------+

在这种情况下,您只返回了感兴趣的节点和关系的属性。您可以通过点表示法 identifer.property 在任何地方访问它们。

当然,这只会列出 T. Hanks 在阿甘正传中扮演的阿甘角色,因为那是您添加的所有数据。

现在您已经了解了如何将新节点添加到现有节点,并且可以组合 MATCHCREATE 来将结构附加到图。

Cypher 示例

让我们看一些使用 MATCHRETURN 关键字的示例。每个后续示例都比上一个示例更复杂。最后两个示例从解释我们试图实现的目标开始。如果您单击每个 Cypher 代码段下面的运行查询按钮,您可以在图或表的格式中看到结果。

  • 示例 1:查找图中标记为 Person 的节点。请注意,如果您想在 RETURN 子句中检索节点,则必须为 Person 节点使用变量,例如 p

MATCH (p:Person)
RETURN p
LIMIT 1
  • 示例 2:查找图中名称为 '汤姆·汉克斯' 的 Person 节点。请记住,您可以将变量命名为任何您想要的内容,只要您稍后引用相同的名称即可。

MATCH (tom:Person {name: 'Tom Hanks'})
RETURN tom
  • 示例 3:查找汤姆·汉克斯执导了哪部 Movie

说明:首先,您应该找到汤姆·汉克斯的 Person 节点,然后找到他连接到的 Movie 节点。为此,您必须从汤姆·汉克斯的 Person 节点到 Movie 节点跟踪 DIRECTED 关系。您还指定了 Movie 标签,以便查询只查看具有该标签的节点。由于您只关心返回电影,因此您需要为该节点指定一个变量(movie),但无需为 Person 节点或 DIRECTED 关系指定变量。

MATCH (:Person {name: 'Tom Hanks'})-[:DIRECTED]->(movie:Movie)
RETURN movie
  • 示例 4:查找汤姆·汉克斯执导了哪部 Movie,但这次只返回电影的标题。

说明:此查询类似于上一个查询。示例 3 返回了包含所有属性的整个 Movie 节点。对于此示例,您仍然需要找到汤姆的电影,但现在您只关心它们的标题。您应该使用语法 variable.property 访问节点的 title 属性以返回名称值。

MATCH (:Person {name: 'Tom Hanks'})-[:DIRECTED]->(movie:Movie)
RETURN movie.title

返回值的别名

并非所有属性都像上面的 movie.title 示例那样简单。由于属性长度、多词描述、开发人员术语和其他快捷方式,一些属性的名称很差。这些命名约定可能难以阅读,尤其是在它们最终出现在报告和其他用户界面上时。

命名不佳的属性
//poorly-named property
MATCH (tom:Person {name:'Tom Hanks'})-[rel:DIRECTED]-(movie:Movie)
RETURN tom.name, tom.born, movie.title, movie.released

就像 SQL 一样,您可以使用 AS 关键字重命名返回结果,并将属性用更清晰的名称别名化。

使用别名获得更清晰的结果
//cleaner printed results with aliasing
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

以下是数据库中的结构

cypher intro patterns in practice05 arr

重要的是要记住,您可以为节点和关系分配变量,并在以后使用它们,无论它们是创建的还是匹配的。

可以在单个 `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
cypher intro patterns in practice06 arr

如果关系的方向是任意的,您可以省略箭头。`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

这是创建的图结构

cypher intro patterns in practice07 arr

这里没有针对两个 `Month` 节点进行全局搜索;它们只在 `2014` `Year` 节点的上下文中进行搜索。

代码挑战

现在您已经了解了基础知识,请使用以下部分构建一个 Cypher 语句,以查找汤姆·汉克斯 `:DIRECTED` 的每个 `:Movie` 的 `title` 和 `release` 年份。单击各个部分以按顺序添加它们,完成后,单击 **运行查询** 以查看您是否正确。您可以单击代码块内的查询的任何部分以将其删除。

MATCH (p:Person {name: "Tom Hanks"})-[:DIRECTED]->(m:Movie) RETURN m.title, m.released