实践中的模式
创建和返回数据
让我们先看看允许您创建数据的子句。
要添加数据,您只需使用已知的模式。通过提供模式,您可以指定要作为图的一部分的图结构、标签和属性。
显然,最简单的子句称为 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
子句中为要返回的数据指定变量。
|
要查找您到目前为止创建的数据,您可以开始查找所有标记为 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'] | +------------------------------+
在这种情况下,您只返回了感兴趣的节点和关系的属性。您可以通过点表示法 identifer.property
在任何地方访问它们。
当然,这只会列出 T. Hanks 在阿甘正传中扮演的阿甘角色,因为那是您添加的所有数据。
现在您已经了解了如何将新节点添加到现有节点,并且可以组合 MATCH
和 CREATE
来将结构附加到图。
Cypher 示例
让我们看一些使用 MATCH
和 RETURN
关键字的示例。每个后续示例都比上一个示例更复杂。最后两个示例从解释我们试图实现的目标开始。如果您单击每个 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
以下是数据库中的结构
重要的是要记住,您可以为节点和关系分配变量,并在以后使用它们,无论它们是创建的还是匹配的。 |
可以在单个 `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` 节点的上下文中进行搜索。