Neo4j之Pattern模式
文章目录
1. Pattern
Neo4j的属性图由节点和关系组成,其中任何一个都可以有属性。节点代表实体,例如概念、事件、地点和事物。关系连接着成对的节点。
然而,节点和关系可以被认为是低级别的构建模块。属性图的真正优势在于它对连接的节点和关系的模式进行编码的能力。单个节点或关系通常只编码很少的信息,但节点和关系的模式可以编码任意复杂的想法。
Neo4j的查询语言Cypher是以模式为基础的。具体来说,模式被用来匹配所需的图结构。一旦找到或创建了匹配的结构,Neo4j就可以利用它进行进一步的处理。
一个简单的模式,只有单一的关系,连接着一对节点(或者,偶尔,一个节点与它本身): a Person LIVES_IN a City or a City is PART_OF a Country.
复杂的模式,使用多种关系,可以表达任意复杂的概念,并支持各种有趣的用例。例如,我们可能想匹配一个人住在一个国家的实例。下面的Cypher代码将两个简单的模式组合成一个稍微复杂的模式,执行这种匹配。
(:Person) -[:LIVES_IN]-> (:City) -[:Part_OF]-> (:Country)
由图标和箭头组成的图示通常用于可视化图形。文本注释提供标签,定义属性等。
1.1 节点语法
Cypher使用一对小括号来表示一个节点。(). 这让人联想到一个圆形或带有圆形端盖的矩形。下面是一些节点的例子:
()
(matrix)
(:Movie)
(matrix:Movie)
(matrix:Movie {title: 'The Matrix'})
(matrix:Movie {title: 'The Matrix', released: 1997})
最简单的形式,(),代表了一个匿名的、没有特征的节点。如果我们想在其他地方引用该节点,我们可以添加一个变量,例如:(matrix)。一个变量被限制在一个单一的语句中。它在另一条语句中可能有不同的意义或没有意义。
:Movie模式声明了一个节点的标签。这允许我们限制该模式,使其不能匹配(比如)在这个位置上有一个演员节点的结构。
节点的属性,例如标题,被表示为一个键值对的列表,包含在一对大括号中,例如。{name: ‘Keanu Reeves’}。属性可以用来存储信息和/或限制模式。
1.2 关系语法
Cypher使用一对破折号(–)来表示无定向关系。有向关系在一端有一个箭头(<–, -->)。括号内的表达式([…])可以用来添加细节。这可能包括变量、属性和类型信息。
-->
-[role]->
-[:ACTED_IN]->
-[role:ACTED_IN]->
-[role:acted_in {roles: ['Neo']}]->
在关系的括号对中发现的语法和语义与节点的圆括号之间使用的语法和语义非常相似。可以定义一个变量(例如,role),以便在语句的其他地方使用。关系的类型(例如::ACTED_IN)类似于节点的标签。属性(例如,角色)完全等同于节点属性。
1.3 模式语法
结合节点和关系的语法,我们可以表达模式。下面可以是这个领域的一个简单模式(或事实)。
(Keanu:Person:Actor {name:'Keanu Reeves'})-[role:ACTED_IN {roles:['Neo']}]->(matrix:Movie {title: 'The Matrix'})
相当于节点标签,:ACTED_IN模式声明了关系的关系类型。变量(例如,role)可以在语句的其他地方用来指代该关系。
与节点属性一样,关系属性被表示为一个包含在一对大括号内的键/值对的列表,例如。{roles: [‘Neo’]}。在这个案例中,我们为角色使用了一个数组属性,允许指定多个角色。属性可以用来存储信息和/或限制模式。
1.4 模式变量
为了提高模块化程度和减少重复,Cypher允许将模式分配给变量。这允许对匹配的路径进行检查,在其他表达式中使用,等等。
acted_in = (:Person)-[:ACTED_IN]->(:Movie)
acted_in变量将包含两个节点和找到或创建的每个路径的连接关系。有许多函数可以访问路径的细节,例如:nodes(path), relationships(path), and length(path)。
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
2. 模式实战
2.1 创建和返回数据
要添加数据,你只需使用你已经知道的模式。通过提供模式,你可以指定你想让哪些图形结构、标签和属性成为图形的一部分。
显然,最简单的子句叫做CREATE。它创建了你所指定的模式。
对于到目前为止你已经看过的模式,它可能看起来像下面这样。
CREATE (:Movie {title: 'The Matrix', released: 1997})
如果你还想返回创建的数据,你可以添加一个RETURN子句,它指的是你分配给模式元素的变量。
Cypher中的RETURN关键字指定了你可能想从Cypher查询中返回什么值或结果。
你可以告诉Cypher在你的查询结果中返回节点、关系、节点和关系属性,或模式。
RETURN在做写程序时不需要,但在读程序时需要。
在使用RETURN时,前面讨论的节点和关系变量变得很重要。
CREATE (p:Person {name: 'Keanu Reeves', born: 1964})
RETURN p
当然,你也可以创建更复杂的结构,比如有人物信息的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
2.2 模式查询
匹配模式是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
在这种情况下,你只返回你感兴趣的节点和关系的属性。你可以通过点符号identifer.property到处访问它们。
当然,这只列出了T.Hank在《阿甘正传》中扮演的Forrest的角色,因为这是你所添加的所有数据。
现在你知道的足够多了,可以在现有的节点上添加新的节点,并且可以结合MATCH和CREATE来将结构附加到图上。
举例 :
MATCH (p:Person)
RETURN p
LIMIT 1
MATCH (tom:Person {name: 'Tom Hanks'})
RETURN tom
MATCH (:Person {name: 'Tom Hanks'})-[:DIRECTED]->(movie:Movie)
RETURN movie
MATCH (:Person {name: 'Tom Hanks'})-[:DIRECTED]->(movie:Movie)
RETURN movie.title
//poorly-named property
MATCH (tom:Person {name:'Tom Hanks'})-[rel:DIRECTED]-(movie:Movie)
RETURN tom.name, tom.born, movie.title, movie.released
//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`
就像SQL一样,你可以通过使用AS关键字来重命名返回结果,并用一个更简洁的名字来别名该属性。
2.3 加入属性
为了用新的信息来扩展图,你首先要匹配现有的连接点,然后用关系将新创建的节点附加到它们上面。添加《云图》作为汤姆-汉克斯的一部新电影可以这样实现。
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
完成模式
每当你从外部系统获得数据或者不确定某些信息是否已经存在于图中时,你希望能够表达一个可重复的(idempotent)更新操作。
在Cypher中,MERGE子句有这个功能。它的作用类似于MATCH或CREATE的组合,在创建数据之前检查其是否存在。
首先检查边是否会存在,如果不存在的会产生边。
使用MERGE,你定义了一个要找到或创建的模式。通常,和MATCH一样,你只想在你的核心模式中包括要寻找的关键属性。MERGE允许你提供你想在CREATE时设置的额外属性。
如果你不知道你的图是否已经包含云图,你可以再次合并它。
MERGE (m:Movie {title: 'Cloud Atlas'})
ON CREATE SET m.released = 2012
RETURN m
在这两种情况下,你都会得到一个结果:要么是已经在图中的数据(可能不止一行),要么是单一的、新创建的电影节点。
一个没有任何先前分配的变量的MERGE子句要么匹配完整的模式,要么创建完整的模式。它永远不会在一个模式中产生部分匹配和创建的混合。为了实现部分匹配/创建,请确保使用已经定义好的变量来处理不应该被影响的部分。
因此,最重要的是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提供了一个有趣的功能。它只在所提供的节点的直接邻域内对给定的模式进行匹配,如果没有找到该模式,则创建该模式。这对于创建树形结构等来说非常方便。