Cypher图数据库查询语言(1) :Cypher概述
Cypher图数据库查询语言(2) :Cypher基本语法
Cypher图数据库查询语言(3) :Cypher语句-MATCH,OPTIONAL MATCH
Cypher图数据库查询语言(4) :Cypher语句-WHERE
Cypher图数据库查询语言(5) :Cypher语句-START,Aggregation 和 LOAD CSV
Cypher图数据库查询语言(6) :Cypher语句-CREATE,MERGR
Cypher图数据库查询语言(7) :Cypher语句-SET,DELETE,REMOVE
Cypher图数据库查询语言(8) :Cypher语句-FOREACH,CREATE UNIQUE
Cypher图数据库查询语言(9) :Cypher语句-RETURN,ORDER BY
Cypher图数据库查询语言(10) :Cypher语句-LIMIT,SKIP
Cypher图数据库查询语言(11) :Cypher语句-WITH,UNWIND,UNION,CALL
语句可分为三类,包括读语句、写语句和通用语句。
- 读语句:MATCH、OPTIONAL MATCH、WHERE、START、Aggregation和LOAD CSV。
- 写语句:CREATE、MERGR、SET、DELETE、REMOVE、FOREACH和CREATE UNIQUE。
- 通用语句:RETURN、ORDER BY、LIMIT、SKIP、WITH、UNWIND、UNION和CALL。
7 CREATE
CREATE 语句用于创建图元素:节点和关系。
7.1 创建节点
7.1.1 创建单个节点
通过如下语句创建单个节点:
CREATE(n)
7.1.2 创建多个节点
创建多个节点,中间以逗号分隔。
CREATE(n),(m)
7.1.3 创建带有标签的节点
创建带有标签的节点采用如下格式:
CREATE (n:Person)
7.1.4 创建带有多个标签的节点
如下语句在创建节点的时候,为其添加了两个标签。
CREATE(n:Person:Swedish)
7.1.5 创建同时带有标签和属性的节点
当创建一个带有标签的节点时,同时也可以添加属性。
CREATE (n:Person { name:'Andres',title:'Developer'})
7.1.6 返回创建的节点
CREATE (a { name:'Andres' })
RETURN a
7.2 创建关系
7.2.1 创建两个节点之间的关系
要创建两个节点之间的关系,先需要找到这两个节点。一旦节点加载后,就可以简单地创建两者之间的关系。
MATCH (a:Person),(b:Person)
WHERE a.name = 'Node A' AND b.name = 'Node B'
CREATE (a)-[r:RELTYPE]->(b)
RETURN r
7.2.2 创建关系并设置属性
给关系设置属性类似于创建节点时设置节点属性。注意:设置的属性值可以是任意表达式。
MATCH (a:Person),(b:Person)
WHERE a.name = 'Node A' AND b.name = 'Node B'
CREATE (a)-[r:RELTYPE { name:a.name + '<->' + b.name }]->(b)
RETURN r
7.3 创建一个完整路径
当使用CREATE和模式时,模式中所有还不存在的部分都会被创建。
MATCH p = (andres { name:'Andres'}) - [:WORKS_AT]->(neo)<-[:WORKS_AT] - (michael {name:'Michael'})
RETURN p
这个查询创建了三个节点和两个关系,然后将它赋给一个路径(Path)变量并返回它。
7.4 CREATE中使用参数
可以使用map来创建图的实体。map中的所有键值对都会被设置到创建的关系或节点上。在下面的例子中还给节点添加了一个Person标签。 参数:
{
"props" : {
"name" : "Andres",
"position" : "Developer"
}
}
查询:
CREATE (n:Person $props)
RETURN n
用属性参数创建多个节点 通过使用一个Cypher的map数组,它将为每个map创建一个节点。
参数:
{
"props" : [ {
"name" : "Andres",
"position" : "Developer"
}, {
"name" : "Michael",
"position" : "Developer"
} ]
}
查询:
UNWIND $props AS map
CREATE (n)
SET n = map
8 MERGE
MERGE可以确保图数据库中存在某个特定的模式 (Pattern)。如果该模式不存在,那就创建它。
8.1 介绍
MERGE 或者匹配已存在的节点并绑定到它, 或者创建新的然后绑定到它。它有点像 MATCH 和 CREATE 的组合。另外, 可以让你指定让某个数据存在, 不管它是匹配到还是创建它。例如, 可以指定图中必须包含一个特定 name 的 user 节点。如果不存在正确 name 的 user 节点, 那么就会创建一个。
当在整个模式上使用 MERGE时, 要么是整个模式匹配到, 要么是整个模式被创建。 MERGE不能部分地应用于模式, 如果希望部分匹配, 可以将模式拆分为多个 MERGE语句。
8.2 MERGE节点
8.2.1 合并带标签的节点
MERGE (robert:Critic)
RETURN robert, labels(robert)
因为没有包含Critic标签的节点,一个新节点在数据库中创建了。
8.2.2 合并带多个属性的单个节点
合并有多个属性但并不是所有属性都匹配到已存在节点的单个节点。
MERGE (charlie { name:'Charlie Sheen', age:10 })
RETURN charlie
名为'Charlie Sheen'的新节点创建了,因为不是所有属性都在已存在的'Charlie Sheen'节点上匹配到了。
8.2.3 合并同时指定标签和属性的节点
合并单个节点,要求它的标签和属性都能匹配到已存在的节点。
MERGE (michael:Person { name:'Michael Douglas' })
RETURN michael.name, michael.bornIn
'Michael Douglas' 节点被匹配到,同时返回它的name和bornIn属性。
8.2.4 合并属性来自已存在节点的单个节点
当绑定节点的属性‘p’来自一个节点集时,如果‘p’存在重复,创建的时候只会创建一次。
MATCH (person:Person)
MERGE (city:City { name:person.bornIn})
RETURN person.name, person.bornIn, city
本例中创建了三个City节点,它们的name属性分别为"New York"、"Ohio"和"New Jersey"。注意:尽管MATCH匹配的结果总有三个节点的bornIn属性值都为"New York",但只创建了一个"New York"节点。因为第一次匹配的时候,"New York"未匹配到,因此创建一个。然而,新创建的"New York"被第二个和第三个匹配到了。
8.3 MERGE 在 CREATE 和 MATCH 中的使用
8.3.1 MERGE 与 CREATE搭配
检查节点是否存在,如果不存在则创建它并设置属性。
MERGE (keanu:Person { name:'Keanu Reeves'})
ON CREATE SET keanu.created = timestamp()
RETURN keanu.name, keanu.created
本查询创建了keanu节点,并设置created属性为创建的时间戳。
8.3.2 MERGE 与 MATCH 搭配
匹配节点,并在找到的节点上设置属性。
MERGE (person:Person)
ON MATCH SET person.found = TRUE
RETURN person.name, person.found
本查询找到所有的Person节点,并设置found属性为true,然后返回它们。
8.3.3 MERGE 与 CREATE 和 MATCH 同时使用
检查节点是否存在,如果不存在,则创建它并设置属性。
MERGE (keanu:Person { name:'Keanu Reeves'})
ON CREATE SET keanu.created = timestamp()
ON MATCH SET keanu.lastSeen = timestamp()
RETURN keanu.name, keanu.created, keanu.lastSeen
本查询创建了'keanu'节点,并设置created属性为创建的时间戳。如果'keanu'已存在,将为它设置一个新属性'lastSeen'。也就是说,当'keanu'不存在时,创建后的'keanu'节点将没有'lastSeen'属性。
8.3.4 利用 MERGE 和 MATCH 设置多属性
如果需要设置多个属性,将它们简单地以逗号分开即可。
MERGE (person:Person)
ON MATCH SET person.found = TRUE, person.lastAccessed = timestamp()
RETURN person.name, person.found, person.lastAccessed
8.4 MERGE关系
MERGE 可用于匹配或创建关系。
MERGE (charlie:Person) { name:'Charlie Sheen'} ), (wallStreet:Movie { title:'Wall Street'})
MERGE (charlie) - [r:ACTED_IN] -> (wallStreet)
RETURN charlie.name, type(r), wallStreet.title
因为'Charlie Sheen'已经在'Wall Street'参演了,所以找到已存的关系并返回。注意:使用MERGE去匹配或创建关系时,必须至少指定一个绑定的节点。
8.4.1 合并多个关系
当MERGE应用于整个模式时,要么全部匹配上,要么全部新创建。
MATCH (oliver:Person { name:'Oliver Stone'}), (reiner:Person{ name:'Rob Reiner'})
MERGE (oliver) - [:DIRECTED] -> (movie:Movie) <- [:ACTED_IN] - (reiner)
在本例中,'Oliver Stone'和'Rob Reiner'从未一起工作过,当试图在他们之间合并一个电影连接时,Neo4j不会使用任何已存在的电影,而是创建一个新的'movie'节点。
8.4.2 合并无方向关系
MERGE也可以用于合并无方向的关系。当需要创建一个关系的时候,它将选择一个任意的方向。
MERGE (charlie:Person) { name:'Charlie Sheen'} ), (oliver:Person { name:'Oliver Stone'})
MERGE (charlie) - [r:KNOWS] - (oliver)
RETURN r
因为'Charlie Sheen'和'Oliver Stone'相互不认识,所以MERGE查询将在他们之间创建一个KNOWS关系。创建的关系的方向是任意的。
8.4.3 合并已存在两节点之间的关系
MERGE可用于连接前面的MATCH和MERGE语句,在两个绑定的节点m和n上创建一个关系。m节点是MATCH语句返回的,而n节点是前面的MERGE语句创建或者匹配到的。
MATCH (person:Person)
MERGE (city:City { name: person.bornIn})
MERGE (person) - [r:BORN_IN] -> (city)
RETURN person.name, person.bornIn, city
第二个MERGE在每个人和他的bornIn属性对应的城市之间创建了一个BORN_IN关系。
8.4.4 合并一个已存在节点和一个合并节点之间的关系
MERGE能够同时创建一个新节点n和一个已存在节点m与n之间的关系。
MATCH (person:Person)
MERGE (person) - [r:HAS_CHAUFFEUR] -> (chauffeur:Chauffeur { name:person.chauffeurName})
RETURN person.name, person.chauffeurName, chauffeur
在本例中,MERGE未匹配到,这里没有标签为Chauffeur的节点和HAS_CHAUFFEUR关系。MERGE创建了5个带有Chauffeur标签的节点,每个节点包含一个name属性,属性的值来自每个匹配到的Person节点的chauffeurName属性的值。MERGE同时还在每个Person节点与新创建的Chauffeur节点之间创建了一个HAS_CHAUFFEUR关系。
8.5 用MERGE的唯一约束性约束
当使用的模式涉及唯一性约束时, Cypher可以通过 MERGE来防止获取相冲突的结果。在这种情况下, 至多有一个节点匹配该模式。例如, 给定两个唯一性约束: Person(id) 和 Person(ssn), 如果存在两个不同的节点分别id为12和ssn为437或者只有一个节点有其中一个属性, 那么这样的查询 MERGE(n: Person{id:12, ssn:437})将失败。
下面的例子分别在 Person的name和role属性上创建一个唯一性约束。
CREATE CONSTRAINT ON (n:Person) ASSERT n.name IS UNIQUE;
CREATE CONSTRAINT ON (n:Person) ASSERT n.role IS UNIQUE;
如果节点未找到,使用唯一性约束创建该节点。
查询:
MERGE (laurence:Person { name:'Laurence Fishburne'})
RETURN laurence.name
本查询创建了'laurence'节点。如果'laurence'已经存在,MERGE仅仅匹配已经存在的节点。
使用唯一性约束匹配已存在的节点。
MERGE (oliver:Person { name:'Oliver Stone'})
RETURN oliver.name, oliver.bornIn
'oliver'节点已经存在了,因此MERGE只是匹配它。
8.5.1 唯一约束性与部分分配
当只有部分匹配时,使用唯一性约束合并将失败。
MERGE (michael:Person { name:'Michael Douglas', role:'Gordon Gekko'})
RETURN michael
这里有一个唯一匹配到的name为'Michael Douglas'的节点,但没有具有唯一的role属性为'Gordon Gekko'的节点,因此MERGE匹配失败。
8.5.2 唯一约束性与匹配冲突
当有匹配的冲突结果时,使用MERGE唯一性约束将失败。
MERGE (oliver:Person { name:'Oliver Stone', role:'Gordon Gekko'})
RETURN oliver
8.6 使用map参数
MERGE不支持像CREATE节点时那样使用map参数。要在MERGE中使用map参数,需要显式地使用希望用的属性。如下例所示: 参数
{
"param" :{
"name" : "Keanu Reeves",
"role" : "Neo"
}
}
查询:
MERGE (person:Person { name: $param.name, role:$param.role})
RETURN person.name, person.role