基于neo4j的知识图谱实战演示示例 郝伟 2021/03/01 [TOC]

1. 1 简介

本文将通过我的这几年的生活的一个具体的实际,演示知识图谱的构建和应用过程。 注意:本文需要结合neo4j图数据库进行展示,方可看到实际效果,否则以下内容难以理解。 网址:http://192.168.3.232:7474/browser/

2. 2 准备工具

首先,删除相关内容以便于演示:

-- 删除所有的人和单位。
Match (p:`人`) detach delete p ; Match (c:`单位`) detach delete c

3. 3 知识图谱构建

3.1. 3.1 我是高校教师

2007年我进入安徽理工大学,成为一名大学教师并与王军号成为同事。

-- 我在2007-2014年的状态
Create 
    (hw:人:教师:硕士{name: '郝伟', 性别:'男', 所在城市:'合肥', 生日:'1981/07/13'}),
    (wjh:人:教师:博士{name: '王军号', 性别:'男', 所在城市:'淮南'}),
    (aust:大学:高校:学校:单位{name:'安徽理工大学'}),
    (hw)-[:员工]->(aust),
    (wjh)-[:员工]->(aust)
Return hw, wjh, aust

问题:以下三条语句在删除时,效果是否一样?

Match (n:人{name: '郝伟'}) Detach Delete n
Match (n:教师{name: '郝伟'}) Detach Delete n
Match (n:硕士{name: '郝伟'}) Detach Delete n

注意:在neo4j数据库删除节点时,如果节点有关系,需要加 Detach 才可以删除,否则会报错,比如:

Cannot delete node<465739>, because it still has relationships. To delete this node, you must first delete its relationships.

3.2. 3.2 世界上其他一些人

此时时,这个世界上同时还存在其他一些人,暂时与我还没有任何关系。

-- 世界上还发生着很多的人和事
Create 
    (scb:人{name: '沈传宝', 性别: '男'}),  
    (mws:人{name:'马维士', 性别:'男', 所在城市:'北京'}),
    (ly:人{name:'李岩', 性别:'男', 所在城市:'北京'}),
    (lcy:人:教师{name:'李春艳', 性别:'女', 所在城市:'合肥'})

3.3. 3.3 结婚了

2010年结婚了。我的身份增加了一个:丈夫。

-- 结婚了
Match 
    (hw:人{name: '郝伟'}), (lcy:人{name: '李春艳'})
Set 
    hw:丈夫, lcy:妻子,
    hw.结婚纪念日= '12/28',
    lcy.结婚纪念日= '12/28' 
CREATE
    p1=(hw)-[:丈夫]->(lcy),
    p2=(hw)<-[:妻子]-(lcy)
RETURN
    p1, p2

3.4. 3.4 儿子出生

2011年儿子出生了,我的身份双增加了:父亲。

--  我们有孩子了
Match 
    (hw:人{name:'郝伟'}), (lcy:人{name:'李春艳'})
SET
    hw:父亲, lcy:母亲
CREATE
    (hcz:人:儿子{name:'郝承志', 性别:'男', 所在城市:'淮南'}),
    (hw)-[:父亲{始于:'2011'}]->(hcz),
    (hw)<-[:儿子{始于:'2011'}]-(hcz),
    (lcy)-[:母亲{始于:'2011'}]->(hcz),
    (lcy)<-[:儿子{始于:'2011'}]-(hcz)
RETURN
    hw, lcy, hcz

3.5. 3.5 取得博士学位

2014年10月入学2018年9月毕业,总算拿到了博士,身份又增加了。

Match 
    (hw:人{name: '郝伟'})
Set 
    hw:博士:学生:留学生
Create
    (kut:大学:高校:学校:单位{name:'高知工科大学'}),
    (km:人:导师:教授{name:'松崎公纪', 性别:'男', 国籍: '西班牙'}),
    (ono:人:学生:留学生{name: 'Onofre Coll Luise', 国籍: '西班牙', 性别:'男'}), 
    (vd:人:学生:留学生{name: 'Valade Ganblavesi', 国籍: '俄罗斯', 性别:'男'}), 
    (hw)<-[:博士导师]-(km),
    (hw)-[:同学]->(ono),
    (hw)-[:师兄弟]->(ono),
    (hw)-[:同学]->(vd),
    (hw)-[:毕业于{日期: '2018/09/25', 专业: '信息工程', 方向:'大数据与并行计算'}]->(kut),
    (vd)-[:毕业于{日期: '2019/03/28', 专业: '分子材料'}]->(kut),
    (ono)-[:毕业于{日期: '2019/09/25', 专业: '信息工程', 方向:'图搜索理论'}]->(kut),
    (km)-[:员工{类型:'教员'}]->(kut)
RETURN hw, km, ono, vd, kut

3.6. 3.6 华云安成立

2019年7月,华云安成立了。

-- 沈总创建了华云安
Match
    (scb:人{name: '沈传宝'})
SET
    scb:老板,
    scb:员工
Create
    (huaun:公司:科技公司:企业:单位{name: '北京华云安信息技术有限公司', 所在城市: '北京'}),
    p1=(scb)-[:创建{创建: '2019'}]->(huaun),
    p2=(scb)-[:控股{创建: '2019-2021'}]->(huaun),
    p3=(scb)<-[:老板{创建: '2019-2021'}]-(huaun),
    p4=(scb)-[:员工{类型: '总经理'}]->(huaun)
RETURN p1, p2, p3,p4

3.7. 3.7 成为华云安的员工

身份和关系都增加了。

--我们加入了公司
Match 
    (hw:人{name: '郝伟'}), 
    (mws:人{name:'马维士'}), 
    (ly:人{name:'李岩'}), 
    (huaun:公司{name: '北京华云安信息技术有限公司'})
Set
    hw:员工,
    mws:员工,
    ly:员工
Create
    (hw)-[:员工{类型:'研究员'}]->(huaun),
    (mws)-[:员工{类型:'技术总监'}]->(huaun),
    (ly)-[:员工{类型:'产品经理'}]->(huaun),
    (hw)-[:同事{公司:'北京华云安'}]->(mws),
    (hw)<-[:同事{公司:'北京华云安'}]-(mws),
    (hw)-[:同事{公司:'北京华云安'}]->(ly),
    (hw)<-[:同事{公司:'北京华云安'}]-(ly),
    (mws)-[:同事{公司:'北京华云安'}]->(ly),
    (mws)<-[:同事{公司:'北京华云安'}]-(ly)
RETURN
    hw, mws, ly, huaun

3.8. 3.8 一些更新

-- 公司获得高新企业资质,沈总与电院有合作关系
Match
    (scb:人{name: '沈传宝'}),
    (huaun:公司{name: '北京华云安信息技术有限公司'})
Set
    huaun:高新企业
Create
    (lu:人{name:'陆导'}),
    (dy:高校:大学:单位:学校:军校:单位{name:'电院'}),
    (lu)-[:员工]->(dy),
    (scb)-[:合作]->(lu),
    (scb)-[:合作]->(dy)

孩子上学了

Match 
    (hcz:人{name: '郝承志'})
Set
    hcz:学生
Create
    (hs:学校:小学:单位{name: '淮师附小'}),
    (hcz)-[:学生]->(hs)

4. 4 知识应用

4.1. 4.1 查询郝伟的所有同事:直接查询

直接查询查不出沈总。

Match
    (hw:人{name: '郝伟'})-[r:同事]->(c:人) 
RETURN 
    c.name

4.2. 4.2 查询郝伟的全部同事:关系推导

同事的定义:在同一家单位共事的员工。 所以,通过所在公司的员工就能查出。

Match
    (hw:人{name: '郝伟'})-[:员工]->(:单位)<-[:员工]-(c)
RETURN 
    c.name

4.3. 4.3 查询郝伟华云安的同事

使用单位的标签而不是Where或属性子句进行限定。

-- 只看华云安的同事
Match
    (hw:人{name: '郝伟'})-[:员工]->(:公司)<-[:员工]-(c)
RETURN 
    c.name

同理,查询郝校在学校的同事只需修改单位的标签为高校即可。

Match
    (hw:人{name: '郝伟'})-[:员工]->(:高校)<-[:员工]-(c)
RETURN 
    c.name

4.4. 4.4 查询郝承志爸爸的同事

-- 直接查询
Match
    p=(hcz:人{name:'郝承志'})-[:儿子]->(:父亲)-[:同事]->(c:人) 
RETURN 
    c.name

-- 注:在CQL中也支持Where子句,但是效率经常不好
Match
    p=(hcz:人)-[:儿子]->(:父亲)-[:同事]->(c:人) 
Where
    hcz.name='郝承志'
RETURN 
    c.name

-- 根据定义查询
Match
    (:学生{name:'郝承志'})-[:儿子]->()-[:员工]->(:单位)<-[:员工]->(c)
RETURN 
    c.name

4.5. 4.5 查询沈总可能认识的人

暂时分两种情况:

  • 直接认识的人:Match (:人{name:'沈传宝'})-[]->(c1:人) RETURN ID(c1) as id, c1.name as name
  • 间接认识的人:Match (:人{name:'沈传宝'})-[]-(:公司)-[]-(c2:人) RETURN DISTINCT ID(c2) as id, c2.name as name

以上是公开查询的情况,并且这里只查询了两层关系。这里分了两次查询,实际上可以使用Union进行整合,如下所示。 实际上我们可以使用六层理论,查询更多的人,但是随着层数的增加,认识的几率也会大大降低。

Match
    (:人{name:'沈传宝'})-[]->(c1:人)
RETURN 
    ID(c1) as id, c1.name as name
UNION
Match
    (:人{name:'沈传宝'})-[]-(:公司)-[]-(c2:人)
RETURN 
    ID(c2) as id, c2.name as name

注意:结果中有很多重复的内容,Union会自动合并,如果需要全部显示,使用UNION ALL

4.6. 4.6 提问

  1. Onofre 的导师是谁?类似的,松崎教授有几个学生?
  2. 王军号认识李春艳的几率大吗?
  3. 安徽理工大学与高知工科大学知道彼此的存在吗?

5. 5 结论与观点

  • 结论
    • 图数据库中的记录包括节点关系,都是非常重要的信息
    • 节点与关系数据库表对应,但可以方便地表达多重身份且数据唯一
    • 关系是图数据库的核心,是信息计算和推导的重要依赖信息
    • 与传统关系数据库相比,图数据库更加自由,不依赖于预定义表和结构
    • 没有直接关系的实体有机率通过一定的推导算法进行关联
  • 观点
    • 设计理念发生重大变化:由先设计数据库再添加数据的传统模式 转变为 先添加数据再分析使用数据 图数据库设计是数据决定框架 → 要同时考虑需求和能拿到的数据 → 要提高数据获取能力
    • 无时效性或时效性不强的数据需要随着时间的不断积累才会有价值 → 长期的数据收集过程
    • 时效性强的数据必需及时更新才会有价值 → 要有相应的数据获取机制
    • 在现有的数据之上进行信息推导能够产生信息价值,但是依赖于人的经验和理解
    • 新的设计理念过于自由会带来一定的数据冗余 → 适当的冗余能够有助于数据推理

results matching ""

    No results matching ""