Neo4j学习笔记 一

前面有几篇介绍了jgraph,这个java图论库,这篇我们来学习一个非常流行的图数据库neo4j。

为什么要有图数据库

在传统开发过程中,开发者往往会选择将数据结构规范化,为数据模型设计复杂紧密的关系,然后将其塞进关系型数据库中,直到整个数据结构越来越复杂不像原本的样子。比如,在关系型数据库中表示多对多关系往往需要一些冗余的表。但是这在图数据库中是非常自然直观的。

从数据结构层面来说,图论中的顶点和边可以构建任意图形,表达能力强大。此外图论历史悠久,几十年沉淀的算法都可以直接在图数据库中使用。

此外尤其是社交型场景,比如,我们可能需要查找用户的好友,或者好友的好友。这种情况下,对应传统关系型数据库,我们可能会需要反复join用户表,查多层好友的情况下,关系型数据库就难以胜任了。

有哪些图数据库可以选型呢?
这里有同花顺团队的选型文档

https://www.nebula-graph.com.cn/posts/reason-to-choose-a-graph-database

1

Neo4j 虽然从选型文档上看来neo4j并没有性能优势,但是在流行度上还是遥遥领先的。

neo4j的特点

ACID

Neo4j的目标是成为一个图形数据库,并把重点放在数据库上。这意味着你将在Neo4j数据库中得到ACID的全部支持:

  1. A原子性
  2. C一致性
  3. I隔离性
  4. D持久性

支持cypher查询语言

类似于sql,图的增删改查有一套自己的语言。

企业版和社区版

企业版和社区版有一些区别:

1、容量:社区版最多支持 320 亿个节点、320 亿个关系和 640 亿个属性,而企业版没有这个限制;

2、并发:社区版只能部署成单实例,不能做集群。而企业版可以部署成高可用集群或因果集群,从而可以解决高并发量的问题;

3、容灾:由于企业版支持集群,部分实例出故障不会影响整个系统正常运行;

4、热备:社区版只支持冷备份,即需要停止服务后才能进行备份,而企业版支持热备,第一次是全量备份,后续是增量备份;

5、性能:社区版最多用到 4 个内核,而企业能用到全部内核,且对性能做了精心的优化;

6、支持:企业版客户能得到 5X10 电话支持(Neo4j 美国电话、邮件,微云数聚电话、微信、邮件);

区别还是挺大的,尤其是性能上核心的差距和集群化的问题。

访问方式

  1. neo4j shell
  2. neo4j web browser
  3. Java 原生API
  4. Java Driver API
  5. Spring Data Neo4j
    后面会介绍这些访问方式。

核心概念

跟图论中的顶点(vertex)和边(edge)类似,Neo4j也有节点(Node)和关系(Relation)的概念。此外,在图的实际应用中,作为数据库还能支持给节点保存属性信息(Properties),还可以给节点打标签(Labels)用于减少实际查询扫描的节点数。

上面基本涵盖了Neo4j的核心要素,下面我们实际上手看看。

部署

嵌入式模式

嵌入式的方式类似sqlite将Neo4j完全嵌入到你的java应用中,然后你可以直接用java API访问同JVM中的Neo4j实例。

maven中添加依赖

1
2
3
4
5
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>3.5.35</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
public class AppTest {

private static GraphDatabaseService embedded;

@Before
public void setup() {
File dbPath = new File("target/neo4j-db");
embedded = new GraphDatabaseFactory().newEmbeddedDatabase(dbPath);
}
}

创建节点

1
2
3
4
5
6
7
8
9
10
11

@Test
public void create() {
try (Transaction transaction = embedded.beginTx()) {
Node n = embedded.createNode();
n.addLabel(Label.label("Student"));
n.setProperty("name", "zhangsan");
n.setProperty("age", "23");
transaction.success();
}
}

createNode 创建节点,addLabel为节点添加标签,setProperty为节点添加属性。

查询所有节点

1
2
3
4
5
6
7
8
9
@Test
public void list() {
try (Transaction transaction = embedded.beginTx()) {
for (Node n : embedded.getAllNodes()) {
System.out.println(n.getLabels() + " " + n.getAllProperties());
}
transaction.success();
}
}

根据属性查节点

1
2
3
4
5
6
7
8
9
@Test
public void find_property() {
try (Transaction transaction = embedded.beginTx()) {
try (ResourceIterator<Node> nodes = embedded.findNodes(Label.label("Student"), "name", "zhangsan")) {
nodes.stream().forEach(e -> System.out.println(e.getLabels() + " " + e.getAllProperties()));
}
transaction.success();
}
}

在两个节点间创建关系

1
2
3
4
5
6
7
8
9
@Test
public void relation() {
try (Transaction t = embedded.beginTx()) {
Node n1 = embedded.findNode(Label.label("Student"), "name", "zhangsan");
Node n2 = embedded.findNode(Label.label("Product"), "name", "lisi");
n1.createRelationshipTo(n2, RelationshipType.withName("friend"));
t.success();
}
}

执行cql

1
2
3
4
5
6
7
8
9
10
11
@Test
public void cql() {
try (Transaction transaction = embedded.beginTx()) {
try (Result r = embedded.execute("match (n:Student) where n.name = 'lisi' return n ");){
while (r.hasNext()) {
System.out.println(r.next());
}
}
transaction.success();
}
}

后面我们会讨论cql的更多细节。

Server模式

大多数neo4j的实际应用还是会选择把neo4j单独部署为图数据库,就是传统的C-S架构。

Rest

首先Neo4j 3.5以后已经废弃了rest方式调用,4.x已经完全移除了
https://neo4j.com/docs/rest-docs/current/
官方还是推荐cypher的方式访问Neo4j。

Java Driver

非常类似jdbc了,完全以cql(sql)访问和操作数据。

maven 添加依赖

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

创建连接

Driver创建session,对应一个连接。

1
2
3
4
5
6
7
8
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);
}

对比

  • 首先由于neo4j是java开发的,所以嵌入式开发只支持java,但是Server模式能支持大量语言。
  • 嵌入式模式由于不需要网络传输的损耗,所以性能对比server模式有一些优势
  • 从架构上来看,解耦数据库和应用是非常必要的,能提升应用的扩展性。
  • 本文作者: fenix
  • 本文链接: https://fenix0.com/neo4j-01/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC 许可协议。转载请注明出处!