Neo4j学习笔记 二

本篇我们详细学习Cypher。

什么是cypher?

类似sql专用于结构化数据,Cypher(后面简称cql)是一种专用于图的声明查询语言。我们通常会使用cql操作neo4j的数据,这比直接操作图数据库的节点和边更高效。

怎么使用cql?

一种方式就是类似java 的MySQL driver

1
2
3
4
5
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>4.2.0</version>
</dependency>

我们这里配置maven java driver。

使用driver连接neo4j

1
2
3
4
5
6
7
8
9
10

private Session session;
private Driver d;

@Before
public void setup() {
d = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "neo4j"));
session = d.session();
}

然后就可以简单的执行cql

1
2
3
4
5
6
7
8
@Test
public void listAll() {
List<Record> records = session.readTransaction(t -> {
Result run = t.run("MATCH (n) RETURN n AS node");
return run.list();
});
print(records);
}

browser

也可以访问neo4j自带的 browser,启动neo4j后可以访问 http://localhost:7474/browser/ 即可访问本地的图浏览器

1

可以作为dbms使用,上面可以输出cql,并且带有补全和语法高亮,非常好用。

语法

基本概念

  1. 节点使用 () 表示
  2. 属性使用 {} 表示
  3. 关系使用 [] 表示
    1. 显式关系:
      (a)-[r:Like]->(b)
    2. 隐式关系:
      (a)--(b)

创建节点

格式

1
create (nodename:nodelabel { property })

其中:

  • nodename为节点名可以省略
  • nodelabel为标签,可以添加多个标签
  • property为键值对,其中字符串类型需要用单引号包裹,整数和布尔型不需要

样例

1
create (n:Student {name:'zhangsan'})

也可以创建没有属性的节点

1
create (n:Student)

也可以创建没有标签的节点

1
create (n)

或者是只有属性没有标签的节点

1
create (n {name :'zhangsan'})

或者是多个标签的节点,多个标签用 : 分割

1
create (n:Student:Person {name:'zhangsan',age:22})

查询节点

查询需要用到matchreturn 两个关键字。

1
2
3
4
5
6
7
8
9
10
MATCH 
(
<node-name>:<label-name>
)

RETURN
<node-name>.<property1-name>,
...
<node-name>.<propertyn-name>

其中

  • match类似sql中的from ,sql中的from后面通常跟随一个表,或者一个查询集,表示后面的数据筛选的源头。cql中并没有表的概念,或者可以理解为,所有数据全部在同一个表中,如果我们的查询不添加任何标签(label)图数据库将扫描全部节点。因此,无论是出于便于管理还是性能原因,我们创建节点通常都会根据业务打上标签,查询时match后跟我们要查询的标签。
  • return 则类似sql中的select,这里是对数据的进一步处理,包含结果集字段的筛选,再加工。在cql中我们可以选择属性返回,也可以直接返回节点

查询返回节点

1
match (n:Student) return n

3
这里节点被直接以图的形式展示在browser中。

查询返回属性

1
match (n:Student) return n.name,n.age

2

这里的返回则比较类似结构化数据了

where子句

类似于sql的where,用于给数据集添加过滤条件,通常跟 match 一起用。

where支持众多条件:

  1. 相等

    1
    match (m:Student) where m.name = 'zhangsan' return m

    这里没啥可以说的,基本都会用。

  2. 模糊查询

    1
    match (m:Student) where m.name =~ 'lisi.*' return m

    这里就跟sql有一些区别了。sql的like 在cql中是 =~ 。条件中的% 也被替换为.*

  3. 大于小于

  • 不等于 <>
  • 大于 >
  • 小于 <

过于常见,这里就不举例了。
条件之间的关系支持:

  1. and
  2. or
  3. not
  4. xor

删除节点

可以配合match 和 where 一起使用

1
DELETE <node-name-list>

例1:删除所有节点:

1
match (m) delete m

例2:删除所有年龄大于22岁Student

1
match (m:Student) where m.age > 22 delete m

需要注意的是,如果节点包含关系,则会删除失败,必须先删除关系再删除节点,或者是节点关系同时删除。后面我们会详细讨论关系相关的细节。

Set

set可以用于修改节点的标签或是属性

修改lisi的年龄为24

1
match (n:Student) where n.name = 'lisi' set n.age = 24

给lisi添加标签Teacher

1
match (n:Student) where n.name = 'zhangsan2' set n:Teacher

Remove

用于删除属性

1
2
match (n:Student) where n.name = 'zhangsan' remove n.age

order by

排序字段也和sql完全一致

1
2
3
4
5
6
order by
<node-label-name>.<property1-name>,
<node-label-name>.<property2-name>,
....
<node-label-name>.<propertyn-name>
ASC / DESC

Union

合并两个结果集,和sql也一致,这里要求两个结果集字段相同。

1
2
3
match (n:Student) where n.name  = 'zhangsan' return n.name
union
match (n:Student) where n.name = 'lisi' return n.name

limit skip

类似sql的offset,这里改为了skip

1
match (n:Student) return n limit 10

merge

merge和create非常类似,都是创建节点或者关系,但是有一点非常重要的区别:当执行create时,即使要创建的节点存在也会创建;但是merge则不会创建。这里的存在意味着所有属性,标签完全相同

关系

如果不能创建关系,那也就谈不上图数据库。

如何创建关系?

  1. 在创建节点的同时创建关系

这样的语句会在创建节点的同时创建关系。

1
create (<node_name1>:<node_label>)-[<relation_name>:<relation_label>]->(<node_name2>:<node_label>)

其中[]之间的是关系,有向图的方向表示为-[]->这样的箭头,箭头右边的是被指向的节点。

例子:

1
create (p1:People)-[r:Like]->(p2:People)

还可以为关系添加属性

1
create (c1:City)-[r:Path{distance:100}]->(c2:City)

也可以不指定标签

  1. 创建节点后再创建关系
    如果是在同一个cql中
    1
    2
    3
    create (c1:City)
    create (c2:City)
    create (c1)-[r:Path]->(c2)

如果是想在不同的cql/事务中:

1
2
create (c:City {name:'shanghai'})
create (c:City {name:'beijing'})
1
2
3
match (c1:City),(c2:City)
where c1.name = 'shanghai' and c2.name = 'beijing'
create (c1)-[r:Path]->(c2)

如何查询关系

我们使用match来匹配其关系

1
2
match (c1:City)-[r]->(c2:City)
return c1.name,c2.name

match中我们显式指定出发节点和目标节点的标签和关系的标签,也可以不指定:

1
2
match (c1)-[r:Like]->(c2)
return c1.name,c2.name

也可以匹配多种关系

1
2
match (c1)-[r:Like|:Love]->(c2)
return c1.name,c2.name

匹配多个关系

1
2
match (c1)-[r1:Like]->(c2)-[r2:Love]->(c3)
return c1.name,c2.name,c3

支持匹配路径的模式

1
2
match (c1)-[r:Like|:Love]->(c2)
return c1.name,c2.name

多重路径

1
2
match (c1)-[r:Like*2]->(c2)
return c1.name,c2.name

如何表示权重图?

neo4j原生不支持权重图,但是我们可以用属性实现类似的效果。

1
create (c1:City)-[d:Path{distance:1000}]->(c2:City)
  • 本文作者: fenix
  • 本文链接: https://fenix0.com/neo4j-02/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC 许可协议。转载请注明出处!