乐趣区

关于图数据库:Neo4j-学习笔记一-初遇篇

本周让咱们持续 NoSQL 家族的访谈之旅,本次咱们的采访对象 Neo4J 学生。

为什么要有 Neo4J?

各种数据库事实上都是在形容事实世界上中数据之间的分割,事实世界中一个比拟典型的场景就是关系数据库力有不逮的中央,那就是社交网络,这种重分割的数据。如下图所示:

A 和 B、C、D、E 都是好敌人,这在关系型数据库是典型的多对多关系, 对于多对多的关系,个别关系型的策略是建设一张两头表来形容这种多对多的关系。然而在关系型数据库中形容分割更常见的场景是形容不同数据的建模关系,比方学生和课程表的关系,选课表就存储学生 ID,课程表 ID 等其余必要信息,学生和课程形容的对象是不同的,下面的图形容的数据是雷同的,可能都是社交圈的人。咱们该如何存储这种分割,一张自分割的表?存储跟他分割的信息?像上面这样:

那如果我当初的需要是查问 A 的敌人的敌人呢,那一个简略而无脑的操作就是我想看我敌人的敌人,这只是一层,对应的 SQL 其实很好写:

# 请原谅我还是从 Student 还是
 SELECT * FROM Student WHERE id in ( 
 SELECT studentReleationId  FROM student_releation WHERE studentId in     
 (SELECT studentReleationId FROM student_releation WHERE studentId  = '1')
# 转成 join 的话, 先找出我敌人的敌人的 Id, 而后再做 join,或者子查问
SELECT s2.studentReleationId  FROM student_releation s1 INNER JOIN  student_releation s2 on s1.studentReleationId = s2.studentId
WHERE s1.studentId = '1'

但其实并不举荐 join,假如一个人的社交好友有 100 个,有的其实会更高,那我存储个人信息如果只有三万集体的话,那么存储分割的表就是三百万条数据,这个其实还不算穿插意识的。对于关系型数据库来说大表的 join 是一场劫难,但对于社交软件来说,三万个用户来说是相当少的数据量,对于成熟的社交产品来说,三百万,三千万都有可能。再比方电影关系图,查看某个导演的电影参演的演员,对于关系型数据库来说这个也不是不能做,只是数量下来之后,咱们查问速度是一直在降落的,因为对于表与表之间的关系根本靠 join,join 的越多速度越慢。由此咱们就引出了图数据库的利用场景,多对多建模、存取数据。图数据库对关联查问个别都进行针对性优化,比方存储模型上、数据结构、查问算法等,避免部分数据的查问引发全副数据的读取。

关系型数据库有不同的实现,MySQL,Oracle, SQL Server 一样,图数据库也有不同的实现: Neo4j,JanusGraph,HugeGraph。关系型数据库的查询语言是 SQL,图数据库的查询语言是: Gremlin、Cypher. 本次咱们介绍的就是 Neo4j。

用起来

我首先还是来到 Neo4j 官网心愿有收费试用的,因为我不想本人装。而后我看到了收费试用:

而后我就不装了,间接开始用。咱们首先还是先介绍根本的语法:

  • 创立

    • 创立结点

      CREATE (Person { name: "Emil", from: "Sweden", klout: 99}) 

      Person 是这个结点的标签,{} 外面是这个标签的属性。

    • 创立分割

      MATCH (ee:Person) WHERE ee.name = "Emil"  #  先查问一次是为了前面建立联系
      CREATE (js:Person { name: "Johan", from: "Sweden", learn: "surfing"}), # 创立一个结点, 并将 js 指向该结点
      (ir:Person { name: "Ian", from: "England", title: "author"}),# 创立一个结点, 并将 ir 指向 这个结点
      (rvb:Person { name: "Rik", from: "Belgium", pet: "Orval"}),
      (ally:Person { name: "Allison", from: "California", hobby: "surfing"}),
      (ee)-[:KNOWS {since: 2001}]->(js),(ee)-[:KNOWS {rating: 5}]->(ir),
      # (变量)-[关系形容]->(变量)  这两个结点建立联系 [中是对这个边的关系形容] KNOWS 能够了解为理解,KNOWS{SINCE:2001} 示意 ee 和 js 意识是在 2001 年
      (js)-[:KNOWS]->(ir),(js)-[:KNOWS]->(rvb),
      (ir)-[:KNOWS]->(js),(ir)-[:KNOWS]->(ally),
      (rvb)-[:KNOWS]->(ally)
    • 移除结点的属性

      MATCH (a:Person {name:'Emil'}) REMOVE a.name
    • 删结点

      MATCH (a:Person {name:'Ian'}) DELETE a
MATCH(ee:Person) where name = 'Johan'
SET ee.name = '张三' RETURN ee; 
# 将 name = Johan 的 name 改为张三 
    • 查找单个结点
    MATCH (ee:Person) WHERE ee.name = "Johan" RETURN ee; # 查出结点中 name 叫 Johan 的, 而后返回 
    • 查找所有具备 Knows 关系的结点
    MATCH (n)-[:KNOWS]-() RETURN n
    • 查找某人敌人的敌人, 这里咱们将 KNOWS 看做敌人
    MATCH (a:Person {name:'Ian'})-[r1:KNOWS]-()-[r2:KNOWS]-(friend_of_a_friend) RETURN friend_of_a_friend.name AS fofName
    # friend_of_a_friend 是返回的变量 

Java 操纵 Neo4J

Java 操纵任何数据库都须要驱动, Neo4j 的收费试用版有对应的语言示例.

Neo4J 的驱动跟 JDBC 相似,原生都是咱们拼 SQL,而后提交。依赖:

 <dependency>
      <groupId>org.neo4j.driver</groupId>
      <artifactId>neo4j-java-driver</artifactId>
      <version>4.1.0</version>
 </dependency>

示例:

public class DriverIntroduction implements AutoCloseable{

    private final Driver driver;

    public DriverIntroduction(String uri, String user, String password, Config config) {
        // The driver is a long living object and should be opened during the start of your application
        driver = GraphDatabase.driver(uri, AuthTokens.basic(user, password), config);
    }
    @Override
    public void close() throws Exception {driver.close();
    }
    public void createFriendship(final String person1Name, final String person2Name) {
        // 创立结点 而后建立联系, 并返回结点
        String createFriendshipQuery = "CREATE (p1:Person { name: $person1_name})\n" +
                "CREATE (p2:Person { name: $person2_name})\n" +
                "CREATE (p1)-[:KNOWS]->(p2)\n" +
                "RETURN p1, p2";

        Map<String, Object> params = new HashMap<>();
        params.put("person1_name", person1Name);
        params.put("person2_name", person2Name);
        try (Session session = driver.session()) {
            Record record = session.writeTransaction(tx -> {Result result = tx.run(createFriendshipQuery, params);
                return result.single();});
        } catch (Neo4jException ex) {throw ex;}
    }
}

总结一下

本文简略介绍了一下 Neo4J 的由来,以及根本的增删改查,Java 操纵数据库。Neo4j 默认只有一个数据库,目前社区版仿佛不反对语法创立数据库,须要批改配置文件。Neo4J 也没有关系型数据库对应表的概念。数据库上面间接就是节点数据。Neo4j 也有中文文档:

http://neo4j.com.cn/public/do…

参考资料

  • 相似 Neo4j 这样的图数据库在国内会衰亡么?为什么?https://www.zhihu.com/questio…
  • 手把手教你疾速入门常识图谱 – Neo4J 教程 https://zhuanlan.zhihu.com/p/…
退出移动版