Cypher 查询语言的增删改查
目录
主要学习资源有:
- Neo4j Cypher Refcard:Cypher 速记卡
- Getting Started with Neo4j - Developer Guides:开发者入门文档合集
关键字
要想在 Neo4j 中增删改查,有几个关键字需要整明白。
MATCH
1:类似SELECT
,查询存在的节点、边、标签、属性、模式等。RETURN
2:指定从查询语句中返回的结果,可以返回节点、边、属性、模式等。要想返回,你需要在MATCH
子句中使用变量。AS
:对返回的变量赋予别名。CREATE
3:类似INSERT
,插入节点、边、模式。盲插,无论存不存在,可能造成重复插入。SET
4:修改节点或边的属性,可增、删、改。可添加日期时间类型5的数据。第一次设置则为添加,第二/n次设置则为修改,设置为null
则是删除属性(也可以用REMOVE
6删除特定属性)。DELETE
7:删除节点、边。删除边需要先找到这条边。删除没有边连接的节点需要先找到这个节点。删除有边连接的节点,你可以分成两个步骤先删除边然后删除节点,也可以使用DETACH DELETE
删除所有与节点相连的边之后删除节点。MERGE
8:先查找再操作,如果没有则添加。如果此次操作是新建ON CREATE
9,如果此次操作是匹配ON MATCH
。
增
// 添加一个类型为 Person 的节点,并用 friend 引用,然后返回结果
CREATE (friend:Person {name: 'Mark'})
RETURN friend
// 找到两个节点,并为它俩添加一条边
MATCH (jennifer:Person {name: 'Jennifer'})
MATCH (mark:Person {name: 'Mark'})
CREATE (jennifer)-[rel:IS_FRIENDS_WITH]->(mark)
// 创建两个节点,并为这两个节点连接一条边。这会重复添加!
CREATE (j:Person {name: 'Jennifer'})-[rel:IS_FRIENDS_WITH]->(m:Person {name: 'Mark'})
// 找到一个节点,并添加一条属性,使用变量 p 引用这个节点,然后返回结果。重复使用该语句会更新属性,而不是重复添加。
MATCH (p:Person {name: 'Jennifer'})
SET p.birthdate = date('1980-01-01') // 这里使用了 date 函数
RETURN p
删
// 找到一条边,并删除这条边
MATCH (j:Person {name: 'Jennifer'})-[r:IS_FRIENDS_WITH]->(m:Person {name: 'Mark'})
DELETE r
// 删除一个节点,这个节点没有任何边与之相联
MATCH (m:Person {name: 'Mark'})
DELETE m
// 找到一个节点,并删除这个节点及其所有边
MATCH (m:Person {name: 'Mark'})
DETACH DELETE m
//delete property using REMOVE keyword
MATCH (n:Person {name: 'Jennifer'})
REMOVE n.birthdate
//delete property with SET to null value
MATCH (n:Person {name: 'Jennifer'})
SET n.birthdate = null
图数据库的属性的删除中,有一种方法是
SET n.birthdate = null
,为什么这么做行?我们知道关系型数据库中这样做是把该字段的值置为null
,而图数据库呢?图数据库只存储对数据有意义的属性和值,这意味着节点和边可有不同类型和不同数量的属性10。
改
// 找到一条边,并用变量 rel 引用,然后修改 rel 边的属性,最后返回这条边(只会显示属性),如果要显示节点,则需要返回 p,rel,c
MATCH (:Person {name: 'Jennifer'})-[rel:WORKS_FOR]-(:Company {name: 'Neo4j'})
SET rel.startYear = date({year: 2018})
RETURN rel
查
// 返回一个 Person 节点
MATCH (p:Person)
RETURN p
LIMIT 1
// 返回所有的具有 name为'Tom Hanks' 属性的 Persion 节点
MATCH (tom:Person {name: 'Tom Hanks'})
RETURN tom
// 返回所有的 Tom Hanks 执导的电影名称
MATCH (:Person {name: 'Tom Hanks'})-[:DIRECTED]->(movie:Movie)
RETURN movie.tilte
// 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`
避免重复数据
之前用 CREATE
的时候可能产生重复数据,解决的办法之一是使用 MERGE
。
MERGE
做的是 select or insert
的事,它首先检索数据存在与否,如果存在则直接返回(或直接做修改),否则先创建数据。
// 查找一个节点,如果不存在则插入
MERGE (mark:Person {name: 'Mark'})
RETURN mark
// 查找一条边,如果不存在则插入
MATCH (j:Person {name: 'Jennifer'})
MATCH (m:Person {name: 'Mark'})
MERGE (j)-[r:IS_FRIENDS_WITH]->(m) // 为什么只在这里使用 MERGE ?
RETURN j, r, m
// 以下语句,会创建重复的两个节点!
MERGE (j:Person {name: 'Jennifer'})-[r:IS_FRIENDS_WITH]->(m:Person {name: 'Mark'})
RETURN j, r, m
// 如果新建模式则设置 since 属性,如果匹配模式则修改 updated 属性
MERGE (m:Person {name: 'Mark'})-[r:IS_FRIENDS_WITH]-(j:Person {name:'Jennifer'})
ON CREATE SET r.since = date('2018-03-01')
ON MATCH SET r.updated = date()
RETURN m, r, j
MERGE
会查找整个 Pattern 模式存不存在,如果模式不存在(包括节点、边、属性),就会新建10。 所以,你需要先查找已经存在的数据,然后使用MERGE
来创建你可能会创建的数据。 也许,你想在新建模式的时候初始化一些属性,,或者想匹配模式的时候修改一些属性,那么在这种情况下,可使用ON CREATE
或ON MATECH
结合SET
。【如果创建了模式,您想初始化某些属性,如果仅匹配,则更新其他属性】