实践中的模式
创建并返回数据
让我们从允许您创建数据的子句开始。
要添加数据,您只需使用已知的模式。通过提供模式,您可以指定希望将哪些图结构、标签和属性作为图的一部分。
显然,最简单的子句是 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
在任何地方访问它们。
当然,这只列出了汤姆·汉克斯在《阿甘正传》中饰演阿甘的角色,因为这是您添加的所有数据。
现在您已了解足够的知识,可以将新节点添加到现有节点,并可以结合使用 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:查找汤姆·汉克斯导演的
Movie
。
解释:首先,您应该找到汤姆·汉克斯的 Person
节点,然后找到他连接到的 Movie
节点。为此,您必须从汤姆·汉克斯的 Person
节点沿着 DIRECTED
关系找到 Movie
节点。您还指定了 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 |
附加结构
要用新信息扩展图,您首先匹配现有的连接点,然后通过关系将新创建的节点附加到它们。将《云图》作为汤姆·汉克斯的新电影,可以这样实现
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
子句中同时附加节点和关系。但为了可读性,最好将它们分开。
|
完成模式
每当您从外部系统获取数据或不确定图中是否已存在某些信息时,您都希望能够表达可重复(幂等)的更新操作。在 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
最重要的是确保您不会创建重复的信息或结构,但其代价是需要首先检查现有匹配项。尤其是在大型图中,扫描大量带标签的节点以查找特定属性可能代价高昂。您可以通过创建支持索引或约束来缓解其中一些问题,这将在后续章节中讨论。但这仍然不是免费的,因此只要您确定不会创建重复数据,请使用 CREATE
而非 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
节点的上下文中进行搜索。