添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

创建

简单创建一个节点

1




    

2
3
4
5
6
7
create(
dis:Disease{
oid: "xxx1",
code: "111",
name: "2hh"
}
)

注意:create也可以和return搭配,直接返回结果。

当然, create 也可以同时创建多个关系:

1
create (m),(s)

简单的创建一个关系线

比如已经有了两个节点,我们想关联上关系:

1
2
3
4
5
6
7
8
match(
a: Disease
), (
b: Disease
)
where a.code="111" and b.code="d1"
create (a)-[r:type]->(b)
return *

如果我们想给这个线设置一些属性,也没什么问题:

1
2
3
4
5
6
7
8
9
10
11
match(
a: Disease{
code: '111'
}
), (
b: Disease{
code: 'd1'
}
)
create(a) -[r:relation{name : a.name + '--' + b.name}]->(b)
return type(r), r.name

这样查出来的结果是:
Alt text
可以看到,我们成功的设置了 r.name .

当然,刚才我们是假设节点已经存在的情况,当然也可以假设不存在节点,直接创建节点+关系了。

1
2
create p=(reba:Person{name: 'reba'})-[:WORK_AT]->(nazha:Person{name:'nazha'})<-[:WORK_AT]-(jt:Person{name: 'jt'})
return p

成功图如下:
Alt text

删除

清空数据库(慎用)

对于节点比较少的可以使用:

1
match (n) detach delete n

对于节点比较多的:
1、停掉服务;
2、删除 graph.db 目录;
3、重启服务。

delete 删除节点和关系

首先不删除干净连接的节点和关系是不能删除一个节点的。

比如首先有这个图:
Alt text

可见它是没有清除干净关系的,现在我们想删除它:

1
match(p:Person{name:'jt'}) delete p

执行的时候发现报 Neo.ClientError.Schema.ConstraintValidationFailed 的错。

我们找一个没有任何连接关系的进行删除,就没毛病了:

1
match(p:Person{id:124}) delete p

还有一种方式,就是删除一个节点,连带着它的关系全部删除,刚刚上面这种执行错误的,加一个 detach 关键字即可解决。

1
2
3
4
match(p:Person{
name: 'jt'
})
detach delete p

还有一种情况,我们只想删除关系,该怎么办?当然也是能够解决的:
我们现在有这样一个关系图:
Alt text

想把他们之间的关系删除掉,该怎么办?

1
match(p:Person{name: "reba"})-[r:WORK_AT]->() delete r

这样就能够把两者之间的关系给删除掉了!

remove 删除节点和关系中的属性字段

首先我们有这样一个节点:
Alt text

1
2
3
4
5
{
"name": "诊断",
"code": "d1",
"oid": "xxx1"
}

用下面这段代码直接进行删除属性:

1
2
3
match(d:Disease{name:"诊断"})
remove d.code
return d.name, d.oid, d.code

结果变成:
Alt text

除了删除属性,我们还能删除 label ,什么是label呢?其实就是类名,比如用下面这段话,把刚刚 诊断 的类删掉:

1
2
3
match(d:Disease{name:"诊断"})
remove d:Disease
return d.name, d.oid, d.code

改(SET)

修改/添加属性

最简单的进行修改一个属性:

1
2
3
match(n {name: 'Andy'})
set n.surname = 'Taylor'
return n.name, n.surname

这里有一点需要注意的是,如果本身没有 surname 这个属性,会自动增加属性。

还有一个高级写法,用到了 case when

1
2
3
4
5
6
7
match(n{name: 'Andy'})
set(
case
when n.age = 36
then n End
).wordIn = 'Malmo'
return n.name, n.wordIn

这里 如果不满足 age=36 便不会执行下面的语句,这样的话,返回的就是一个 null ,比如:
Alt text

一次修改/添加多个属性

1
2
3
match(n{name: 'Peter'})
set n.a1= '1' , n.a2 = '3'
return n

删除一个属性

将这个属性置为 null ,就是删除一个属性,如下:

1
2
MATCH (n { name: 'Andy' })
SET n.name = NULL RETURN n.name, n.age

删除所有的属性使用一个空的map和等号

这样即可删除节点所有的属性了。

1
2
3
MATCH (p { name: 'Peter' })
SET p = { }
RETURN p.name, p.age

完全copy一个节点或者关系

SET可用于将所有属性从一个节点或关系复制到另一个节点。这将删除复制到的节点或关系上的所有其他属性。

1
2
3
MATCH (at { name: 'Andy' }),(pn { name: 'Peter' })
set at = pn
return at.name, at.age, at.hungry, pn.name, pn.age

注意看两个参数!

设置一个节点属性所有从map中

1
2
3
MATCH (p { name: 'Peter' })
SET p = { name: 'Peter Smith', position: 'Entrepreneur' }
RETURN p.name, p.age, p.position

请注意,这个操作会删除原来所有的节点!那有没有不删除所有的做法呢?当然有:

设置一个节点所有属性,但是不覆盖原来的属性

其实和上面几乎一样,就是把 = 变成 +=

1
2
3
match (p{name: 'Peter'})
SET p += { age: 38, hungry: TRUE , position: 'Entrepreneur' }
RETURN p.name, p.age, p.hungry, p.position

修改类(label)

修改一个:

1
2
3
MATCH (n { name: 'Stefan' })
SET n:German
RETURN n.name, labels(n) AS labels

修改多个:

1
2
3
match(n{name: 'Peter'})
set n:Swedish:Bossman
return n.name, labels(n) as labels

查询

简单的查询一个节点

1
2
3
4
match(
d: Disease
)
return d

简单进行条件类型的查询

1
2
3
4
5
6
match(
d: Disease{
oid: "xxx1"
}
)
return d

Return

return 的作用是在match匹配上了以后,选择哪些返回,如果能确定返回的属性,尽量不要全部返回!

  • Return的语法很简单,需要什么就返回什么,*表示返回所有的。
  • 1
    2
    MATCH p =(a { name: 'A' })-[r]->(b)
    RETURN *

    返回的结果就是所有的可能性:
    Alt text

  • return 中,还可以像传统sql那样,通过as来改名:
  • 1
    2
    MATCH (a { name: 'A' })
    RETURN a.age AS SomethingTotallyDifferent
  • 对于没有属性的会返回一个 null ,比如:
    1
    2
    MATCH (n)
    RETURN n.age

    如果返回的两个结果,一个由age这个属性,一个没有,那么有的正常返回,没有的返回 null

  • 还可以像Java一样返回一个布尔运算,并且返回的是多个元素也支持:
    1
    2
    MATCH (a { name: 'A' })
    RETURN a.age > 30, "I'm a literal",(a)-->()

    返回的是:
    Alt text

  • 当然你也可以和 DISTINCT 连着用
    1
    2
    MATCH (a { name: 'A' })-->(b)
    RETURN DISTINCT b

    OPTIONAL MATCH

    这个和match差不多,区别在于当没有查到东西的时候,会返回一个 null

    比如下面这句话:

    1
    2
    3
    4
    5
    match(p:Person{
    name: 'reba'
    })
    optional match (p) -->(x)
    return x

    可见是有值的,但是如果我们把指向方向换一下,变成:

    1
    2
    3
    4
    5
    match(p:Person{
    name: 'reba'
    })
    optional match (p) <--(x)
    return x

    同样的,如果我们把 optional 去掉,结果是:
    Alt text

    MERGE关键字

    这个关键字基本上是把create和match合并到一起,先看一个最简单的用法:

    1
    2
    merge (robert:Critic{name: '111'})
    return robert, labels(robert)

    本身是不存在这个节点的,所以会直接创建,那么把这句话再执行一遍,发现此时的作用只是相当于 match 了。

    当然也可以从已经存在的节点中获取值,比如:

    1
    2
    3
    MATCH (person:Person)
    MERGE (city:City { name: person.bornIn })
    RETURN person.name, person.bornIn, city

    从已经存在的节点中,获取一些属性值,然后进行复制。当然,这个操作可以是批量的!

    比如此处的结果是:
    Alt text

    on create

    这个实际上是一个限定条件,表达的是当创建的时候,才执行,不创建就不执行,比如:

    1
    2
    3
    merge (c:Critic{name:'1112'})
    on create set c.create = timestamp()
    return c.name, c.create

    这个语句中,如果数据库中已经存在了一个 1112 那么就不会 set 值,同样,如果不存在,那么就会执行 set 后面的部分。

    on match

    这个命令和上述表达差不多,不同的是它是匹配上了就进行 set

    1
    2
    MERGE (person:Person)
    ON MATCH SET person.found = TRUE RETURN person.name, person.found

    当然也可以同时设置多个属性值:

    1
    2
    3
    MERGE (person:Person)
    ON MATCH SET person.found = TRUE , person.lastAccessed = timestamp()
    RETURN person.name, person.found, person.lastAccessed

    on create 和on match 合并

    1
    2
    3
    4
    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

    现在数据库中是没有这个节点的,也就是说会进行创建,那么我们看看最后的结果:
    Alt text

    很明显 MATCH 后面的没有执行!

    Merge relationships

    MERGE 同样也能被用来 match 或者 create 关系。

    比如已经存在两个节点,想给他们MERGE一下关系:

    1
    2
    3
    MATCH (charlie:Person { name: 'Charlie Sheen' }),(wallStreet:Movie { title: 'Wall Street' })
    MERGE (charlie)-[r:ACTED_IN]->(wallStreet)
    RETURN charlie.name, type(r), wallStreet.title

    当然,我们也能够一下子处理多个关系,比如:

    1
    2
    3
    MATCH (oliver:Person { name: 'Oliver Stone' }),(reiner:Person { name: 'Rob Reiner' })
    MERGE (oliver)-[:DIRECTED]->(movie:Movie)<-[:ACTED_IN]-(reiner)
    RETURN movie

    最后结果是:
    Alt text

    还可以创建一个无向的连接:

    1
    2
    3
    MATCH (charlie:Person { name: 'Charlie Sheen' }),(oliver:Person { name: 'Oliver Stone' })
    
    
    
    
        
    
    MERGE (charlie)-[r:KNOWS]-(oliver)
    RETURN r

    批量操作

    有一些批量操作的写法,能够帮助我们快速创建大量节点和关系,比如:

    1
    2
    3
    4
    MATCH (person:Person)
    MERGE (city:City { name: person.bornIn })
    MERGE (person)-[r:BORN_IN]->(city)
    RETURN person.name, person.bornIn, city

    将所有 Person 中出生地和实际的城市直接挂钩!

    最后结果是: Alt text

    上面这句话,我们还可以改写下:

    1
    2
    3
    MATCH (person:Person)
    MERGE (person)-[r:BORN_IN]->(city:City { name: person.bornIn })
    RETURN person.name, person.bornIn, city

    限定条件WHERE

    首先我们有这样一张图:

    对于 where ,没什么好讲的,和传统的sql中差不多:
    比如下面这句话:

    1
    2
    3
    MATCH (n)
    WHERE n.name = 'Peter' XOR (n.age < 30 AND n.name = 'Timothy') OR NOT (n.name = 'Timothy' OR n.name = 'Peter')
    RETURN n.name, n.age

    对label进行过滤

    下面这句话可以直接对label进行过滤:

    1
    2
    3
    MATCH (n)
    WHERE n:Swedish
    RETURN n.name, n.age

    不固定属性的过滤

    1
    2
    3
    4
    with 'AGE' as propname
    match (n)
    where n[toLower(propname)] < 30
    return n.name, n.age

    属性存在性校验

    1
    2
    3
    MATCH (n)
    WHERE exists(n.belt)
    RETURN n.name, n.belt

    以xx字符串开头的写法

    1
    2
    3
    MATCH (n)
    WHERE n.name STARTS WITH 'Pet'
    RETURN n.name, n.age

    以xx字符串结尾

    1
    2
    3
    MATCH (n)
    WHERE n.name ENDS WITH 'ter'
    RETURN n.name, n.age

    字符串包含

    1
    2
    3
    MATCH (n)
    WHERE n.name CONTAINS 'ete'
    RETURN n.name, n.age

    NOT 的使用

    1
    2
    3
    MATCH (n)
    WHERE NOT n.name ENDS WITH 'y'
    RETURN n.name, n.age

    正则表达式的使用

    1
    2
    3
    MATCH (n)
    WHERE n.name =~ 'Tim.*'
    RETURN n.name, n.age

    还有一种不区分大小写的写法:

    1
    2
    3
    MATCH (n)
    WHERE n.name =~ '(?i)AND.*'
    RETURN n.name, n.age

    根据null过滤

    1
    2
    MATCH (person)
    WHERE person.name = 'Peter' AND person.belt IS NULL RETURN person.name, person.age, person.belt

    ORDER BY

    首先记住,不能根据关系或者节点进行排序,只能根据属性!

    然后看一个简单的写法:

    1
    2
    3
    MATCH (n)
    RETURN n.name, n.age
    ORDER BY n.age, n.name

    一般 order by 都是放在 return 后面

    SKIP

    从头开始跳过几个数据,一般在Order by 的后面,如果没有order by 就放在return后面:

    来看一个稍微高级点的写法:

    1
    2
    3
    4
    MATCH (n)
    RETURN n.name
    ORDER BY n.name
    SKIP toInteger(3*rand())+ 1

    LIMIT

    limit 一般是在最后了,控制展示的个数:

    1
    2
    3
    4
    MATCH (n)
    RETURN n.name
    ORDER BY n.name
    LIMIT toInteger(3 * rand())+ 1

    WITH

    假设现在有这样一张图:
    Alt text

    对聚合函数结果进行筛选

    我们用这样一段话,来查询

    1
    2
    3
    4
    match(David{name: 'David'}) --(otherPerson)-->()
    with otherPerson, count(*) as cnt
    where cnt > 1
    return otherPerson.name

    这句话表达的是 David 连接过去的节点,它向外连接关系大于1的那个节点。
    所以很明显,就是 Anders

    1
    2
    3
    4
    match(Anders{name: 'Anders'}) --(otherPerson)-->()
    with otherPerson, count(*) as cnt
    where cnt > 1
    return otherPerson.name

    这个结果很明显就是 Bossman 了。

    在使用collect之前对结果进行排序

    1
    2
    3
    4
    match(n)
    with n
    where n.name = 'David' or n.name = 'Bossman'
    return collect(n.name)

    限制搜索路径分支

    1
    2
    3
    4
    5
    MATCH (n { name: 'Anders' })--(m)
    WITH m
    ORDER BY m.name DESC LIMIT 1
    MATCH (m)--(o)
    RETURN o.name

    最后结果是:
    Alt text

    总结一下, With 关键字是连接多个查询的结果,即将上一个查询的结果用作下一个查询的开始。

    unwind

    unwinding a list

    我们先看这样一句话,初步了解下 unwind 的用法:

    1
    2
    unwind [1, 2, 3, NULL] as x
    return x, 'val' as y

    creating a distinct list

    1
    
    
    
    
        
    
    2
    3
    4
    with [1, 1, 2, 2] as coll
    unwind coll as x
    with distinct x
    return collect(x) as setOfVals

    Using UNWIND with any expression returning a list

    其实是在合并列表

    1
    2
    3
    with [1, 2] as a, [3, 4] as b
    unwind (a + b) as x
    return x

    Using UNWIND with a list of lists

    1
    2
    3
    4
    with [[1, 2], [3, 4], 5] as nested
    unwind nested as x
    unwind x as y
    return x, y

    Using UNWIND with an empty list

    这是一个用法,只要 unwind 的是一个 [] ,那么不管一起返回的是什么,都会返回一个 0rows

    1
    2
    unwind [] as empty
    return empty, 'literal_that_is_not_returned'

    Using UNWIND with an expression that is not a list

    unwind 可以被用来检测是不是一个list

    1
    2
    unwind null as x
    return x, 'some_itearl'

    如果我们直接unwind一个数字,会报错:

    1
    2
    unwind 5 as x
    return x, '11'

    FOREACH

    对于这样关系的一张图:
    Alt text

    下面这句话,可以批量的进行修改属性

    1
    2
    3
    match p=(begin)-[*]->(END)
    where begin.name = 'A' And END.name = 'D'
    foreach(n in nodes(p)| set n.marked = TRUE)

    CALL

    使用CALL可以调用一些函数,比如来个最简单的调用一个库函数:

    1
    CALL `db`.`labels`

    这样子可以把我们的所有类名全部列出来:
    Alt text

    但这一部分一般用到的应当不多,不作详细介绍。

    UNION

    union 就是把两个结果合并起来。

    比如:

    1
    2
    3
    4
    MATCH (n:Actor)
    RETURN n.name AS name
    UNION ALL MATCH (n:Movie)
    RETURN n.title AS name

    这样子查出来的结果是:
    Alt text

    如果不用 union all 改直接用 union 呢?

    1
    2
    3
    4
    5
    MATCH (n:Actor)
    RETURN n.name AS name
    UNION
    MATCH (n:Movie)
    RETURN n.title AS name

    相当于取了个重

  •