看完《低智商犯罪》,学习Cypher构建知识图谱

摘要

《低智商犯罪》都看了吧,是否现在还在回味剧情里每一个人物的刻画,以及每一个案件的编排。看完后咱们就来简单的学习一下,如何把剧集里的人,事件以及各种关系,构建成一个简单的知识图谱。

img

首先来看下构建的大致效果:

img

本文完整脚本的下载:

https://github.com/microsoftbi/RAGHUSKY/blob/main/Documents/dzs_knowledge_graph.cypher

以及测试文本的下载:

https://github.com/microsoftbi/RAGHUSKY/blob/main/Documents/DZS_Story.md


1. 核心概念

1.1 图数据库三要素

节点 (Node)  ──→  实体(人、案件、物品、地点、组织)
关系 (Relationship) ──→ 实体之间的连接(调查、杀害、拥有、隶属)
属性 (Property) ──→ 节点和关系上的键值对(name、role、note)

1.2 Cypher 语法基本模式

Cypher 用 ASCII 艺术描述图模式,这是它最核心的设计思想:

// 节点: (变量:标签 {属性})
(p:Person {name: '张一昂'})

// 关系: -[变量:关系类型 {属性}]->
(a)-[:KNOWS {since: 2020}]->(b)

// 方向: → 有向, - 无向
()-->()     // 有向关系
()--()      // 无向关系(查询时忽略方向)

1.3 图模型的构建

┌──────────┐    INVESTIGATES    ┌──────────┐
│  Person  │ ─────────────────→│   Case   │
└──────────┘                   └──────────┘
      │                              │
      │ BELONGS_TO                   │ HAPPENED_AT
      ↓                              ↓
┌──────────┐                   ┌──────────┐
│Organization│                 │ Location │
└──────────┘                   └──────────┘
      │                              │
      │ CONTROLS                     │ DIED_AT
      ↓                              ↓
┌──────────┐    CLUE_TO       ┌──────────┐
│  Person  │ ←────────────────│ Evidence │
└──────────┘                  └──────────┘

5 种节点标签PersonCaseOrganizationLocationEvidence

20+ 种关系类型SUPERIOR_TOKILLEDINVESTIGATESCLUE_TOBELONGS_TO


2. 约束与索引

2.1 唯一性约束 (Uniqueness Constraint)

CREATE CONSTRAINT person_name IF NOT EXISTS
FOR (n:Person) REQUIRE n.name IS UNIQUE;

语法拆解

部分含义
CREATE CONSTRAINT person_name创建名为 person_name 的约束
IF NOT EXISTS幂等保护:已存在则跳过(Neo4j 4.4+)
FOR (n:Person)约束作用于 Person 标签的节点
REQUIRE n.name IS UNIQUE要求 name 属性值唯一

为什么需要约束?

  • 保证 MERGE 能正确匹配已有节点(否则可能创建重复节点)
  • 自动创建索引,加速 MATCH 查询
  • 数据完整性保障

2.2 约束 vs 索引

-- 约束(自动附带索引)
CREATE CONSTRAINT ... REQUIRE ... IS UNIQUE       -- 唯一性约束
CREATE CONSTRAINT ... REQUIRE ... IS NODE KEY     -- 节点键约束(同时唯一+非空)

-- 纯索引(不含约束语义,仅加速查询)
CREATE INDEX person_role FOR (n:Person) ON (n.role);
CREATE TEXT INDEX person_note FOR (n:Person) ON (n.note);  -- 全文索引

2.3 查看与删除

SHOW CONSTRAINTS;
SHOW INDEXES;
DROP CONSTRAINT person_name;

3. 创建节点

3.1 MERGE + SET 模式

脚本中大量使用的模式:

MERGE (p1:Person {name: '张一昂'})
SET p1.role = '刑警',
    p1.identity = '执法人员',
    p1.org = '省公安厅',
    p1.note = '主角,五年前因破案意外被调离刑侦一线,后重新启用';

为什么拆成 MERGE + SET?

-- ❌ 错误写法:将所有属性放入 MERGE
MERGE (p:Person {name: '张一昂', role: '刑警', note: '主角...'});
-- 问题:如果节点已存在但 role 不同,MERGE 会创建新节点(因为整体模式不匹配)

-- ✅ 正确写法:只用唯一键做 MERGE,其余用 SET
MERGE (p:Person {name: '张一昂'})   -- 只用唯一键匹配
SET p.role = '刑警',                 -- SET 总是更新
    p.note = '主角...';

核心原则MERGE 子句中只放唯一标识属性(受约束保护的字段),其余属性用 SET 单独设置。

3.2 MERGE vs CREATE

MERGECREATE
重复执行不创建重复每次创建新节点
匹配已有先查再决定不查直接建
适用场景构建脚本(幂等)明确要新增
-- MERGE: 脚本可重复运行
MERGE (p:Person {name: '张一昂'});

-- CREATE: 每次都生成重复数据(除非确定数据不存在)
CREATE (p:Person {name: '张一昂'});

3.3 多属性 SET 语法

-- 方式1: 逗号分隔(脚本中使用的格式)
SET n.prop1 = 'value1',
    n.prop2 = 'value2',
    n.prop3 = 'value3';

-- 方式2: 映射批量设置
SET n += {prop1: 'value1', prop2: 'value2', prop3: 'value3'};

-- 方式3: 从已有节点复制
MATCH (a:Person {name: '张一昂'}), (b:Person {name: '李茜'})
SET b.org = a.org;  -- 复制 org 属性

3.4 变量命名惯例

MERGE (p1:Person {name: '张一昂'})   -- p1, p2, p3... 人物
MERGE (c1:Case {name: '卢正车祸案'}) -- c1, c2, c3... 案件
MERGE (o1:Organization {name: '省公安厅'}) -- o1, o2... 组织
MERGE (l1:Location {name: '三江口市'}) -- l1, l2... 地点
MERGE (e1:Evidence {name: '残缺举报信'}) -- e1, e2... 证据

变量只在当前语句有效,不需要跨语句保持一致——但良好的命名约定有助于脚本可读性


4. 创建关系

4.1 核心模式:MATCH + MERGE

MATCH (a:Person {name: '高栋'}), (b:Person {name: '张一昂'})
MERGE (a)-[:SUPERIOR_TO {note: '副厅长→下属'}]->(b);

三步分解

Step 1: MATCH (a:Person {name: '高栋'})   → 找到起始节点赋给变量 a
Step 2: MATCH (b:Person {name: '张一昂'}) → 找到目标节点赋给变量 b
Step 3: MERGE (a)-[:SUPERIOR_TO]->(b)     → 创建/匹配关系

为什么不是 MATCH ... CREATE

-- ❌ 每次运行都创建重复关系
MATCH (a:Person {name: '高栋'}), (b:Person {name: '张一昂'})
CREATE (a)-[:SUPERIOR_TO]->(b);

-- ✅ 幂等安全
MATCH (a:Person {name: '高栋'}), (b:Person {name: '张一昂'})
MERGE (a)-[:SUPERIOR_TO]->(b);

4.2 关系方向

(a)-[:SUPERIOR_TO]->(b)    // a 是 b 的上级(有向)
(a)-[:COLLEAGUE_WITH]-(b)  // a 和 b 互为同事(无向)

// 实际使用中,方向取决于语义:
// 张一昂 调查→ 案件:有意义的方向
// 张一昂-同事-李茜:双向等同,但存储时仍需选一个方向,查询时可用 ()--() 忽略方向

4.3 同标签节点间的关系(Person ↔ Person)

脚本 Part 7 中全部是 (Person)-[:REL_TYPE]->(Person) 的模式:

// 上下级:高栋 → 张一昂
MATCH (a:Person {name: '高栋'}), (b:Person {name: '张一昂'})
MERGE (a)-[:SUPERIOR_TO {note: '副厅长→下属'}]->(b);

// 杀害:朗博图 → 叶剑
MATCH (a:Person {name: '朗博图'}), (b:Person {name: '叶剑'})
MERGE (a)-[:KILLED {method: '用绑刀的车撞死', reason: '灭口'}]->(b);

// 勒索:方超 → 周荣
MATCH (a:Person {name: '方超'}), (b:Person {name: '周荣'})
MERGE (a)-[:BLACKMAILED {amount: '2000万', item: '朗博文手机'}]->(b);

同类节点间的关系对照表

关系类型方向示例
SUPERIOR_TO上级→下级高栋→张一昂
COLLEAGUE_WITH张一昂↔李茜
SIBLING_OF朗博文↔朗博图
IN_RELATIONSHIP_WITH陆一波↔周淇
COOPERATES_WITH方超↔刘直
KILLED凶手→受害者朗博图→叶剑
BLACKMAILED勒索者→被勒索者方超→周荣
COVERED_UP_FOR包庇者→被包庇者朗博文→朗博图
REPORTED举报者→被举报者陆一波→周荣
ORDERED指使者→执行者周荣→胡建仁
ARRESTED执法者→被捕者张一昂→李峰
FENCED_TO销赃者→收赃者方超→郑勇兵
TRANSACTED_WITH买方→卖方周荣→朱亦飞

5. 关系属性

5.1 语法

关系也可以携带属性,语法与节点属性相同:

MERGE (a)-[:KILLED {
  method: '用绑刀的车撞死',
  reason: '灭口——叶剑发现了手表线索'
}]->(b);

5.2 何时用关系属性 vs 节点属性

数据特点放哪里示例
描述关系本身的特征关系属性methodamountrole
描述实体自身的特征节点属性nameidentitynote
关系附加的上下文关系属性勒索金额、抓捕地点
实体的固有属性节点属性人名、角色、所属组织

5.3 脚本中关系属性的实际使用

// 杀害关系:记录手段和动机
[:KILLED {method: '火并枪杀', reason: '朱亦飞指使'}]

// 勒索关系:记录金额和筹码
[:BLACKMAILED {amount: '2000万', item: '朗博文手机'}]

// 指使关系:记录任务内容
[:ORDERED {task: '疏通方庸关系、处理各种事务'}]

// 调查关系:记录角色分工
[:INVESTIGATES {role: '主办'}]     // 主办
[:INVESTIGATES {role: '协办'}]     // 协办

6. 跨标签关系

6.1 Person → Case(人物 ↔ 案件)

-- 调查
MATCH (a:Person {name: '张一昂'}), (b:Case {name: '叶剑被害案'})
MERGE (a)-[:INVESTIGATES {role: '主办'}]->(b);

-- 被害
MATCH (a:Person {name: '叶剑'}), (b:Case {name: '叶剑被害案'})
MERGE (a)-[:VICTIM_OF]->(b);

-- 供述
MATCH (a:Person {name: '朗博图'}), (b:Case {name: '叶剑被害案'})
MERGE (a)-[:CONFESSED_TO {note: '在机场被截获后供认'}]->(b);

-- 涉案(通用关联,带角色说明)
MATCH (a:Person {name: '陆一波'}), (b:Case {name: '省城爆炸案'})
MERGE (a)-[:INVOLVED_IN {role: '举报人'}]->(b);

Person → Case 关系语义矩阵

关系说明何时使用
INVESTIGATES调查案件执法人员与案件
VICTIM_OF是案件的受害者死伤者与案件
WITNESSED目击案件目击者与案件
CONFESSED_TO供认罪行罪犯与案件
SUSPECTED_OF涉嫌(不一定真凶)嫌疑人(含被冤枉)
INVOLVED_IN通用关联不适合上述分类时使用

6.2 Evidence → Case(证据 ↔ 案件)

-- 线索
MATCH (a:Evidence {name: '限量电子表'}), (b:Case {name: '卢正车祸死亡案'})
MERGE (a)-[:CLUE_TO {note: '出现在车祸现场视频中'}]->(b);

-- 凶器
MATCH (a:Evidence {name: '绑刀的车'}), (b:Case {name: '叶剑被害案'})
MERGE (a)-[:WEAPON_OF]->(b);

-- 赃物
MATCH (a:Evidence {name: '假玉财神像'}), (b:Case {name: '省城爆炸案'})
MERGE (a)-[:LOOT_OF]->(b);

6.3 Person → Organization(人物 ↔ 组织)

-- 隶属
MATCH (a:Person {name: '张一昂'}), (b:Organization {name: '省公安厅'})
MERGE (a)-[:BELONGS_TO]->(b);

-- 控制(领导关系)
MATCH (a:Person {name: '周荣'}), (b:Organization {name: '荣城集团'})
MERGE (a)-[:CONTROLS]->(b);

BELONGS_TO vs CONTROLS

  • 普通成员用 BELONGS_TO
  • 老板/主管用 CONTROLS(暗示对组织的控制权)
  • 一个人可以同时有两者(如周荣既有 BELONGS_TO 也有 CONTROLS

6.4 Case → Case(案件 ↔ 案件)

-- 一个案件引出另一个
MATCH (a:Case {name: '省城爆炸案'}), (b:Case {name: '卢正车祸死亡案'})
MERGE (a)-[:LED_TO {note: '爆炸案现场的举报信引出卢正案重新调查'}]->(b);

-- 案件间的关联
MATCH (a:Case {name: '叶剑被害案'}), (b:Case {name: '卢正车祸死亡案'})
MERGE (a)-[:LINKED_TO {note: '叶剑因重新调查卢正案发现手表线索而被害'}]->(b);

-- 案件是系列案的一部分
MATCH (a:Case {name: '信用社抢劫案'}), (b:Case {name: '方超刘直连环抢劫案'})
MERGE (a)-[:PART_OF]->(b);

6.5 Person → Location(人物 ↔ 地点)

-- 死于某地
MATCH (a:Person {name: '叶剑'}), (b:Location {name: '河岸边'})
MERGE (a)-[:DIED_AT]->(b);

-- 前往某地
MATCH (a:Person {name: '张一昂'}), (b:Location {name: '周荣庄园'})
MERGE (a)-[:WENT_TO {note: '带队查案,最终在此逮捕周荣'}]->(b);

-- 被困某地
MATCH (a:Person {name: '方超'}), (b:Location {name: '枯井'})
MERGE (a)-[:TRAPPED_IN {note: '踩点时掉入枯井被困三天'}]->(b);

-- 在某地受伤
MATCH (a:Person {name: '李棚改'}), (b:Location {name: '涵洞'})
MERGE (a)-[:INJURED_AT {note: '追捕刚哥小毛时失足摔倒昏迷'}]->(b);

附录:脚本速查表

节点标签与数量

标签数量示例
Person33张一昂、方超、周荣、叶剑
Case10卢正车祸案、叶剑被害案、编钟非法交易案
Organization7省公安厅、荣城集团、枫林晚酒店
Location15三江口市、周荣庄园、河岸边、枯井
Evidence12残缺举报信、限量电子表、一昂血字石头

关系类型速查

关系from → to说明
SUPERIOR_TOPerson→Person上下级
COLLEAGUE_WITHPerson→Person同事
SIBLING_OFPerson→Person兄弟
IN_RELATIONSHIP_WITHPerson→Person情侣/夫妻
COOPERATES_WITHPerson→Person合作搭档
KILLEDPerson→Person杀害
BLACKMAILEDPerson→Person勒索
COVERED_UP_FORPerson→Person包庇顶罪
REPORTEDPerson→Person举报
ORDEREDPerson→Person指使命令
FENCED_TOPerson→Person销赃
TRANSACTED_WITHPerson→Person非法交易
ARRESTEDPerson→Person抓捕
INVESTIGATESPerson→Case调查案件
VICTIM_OFPerson→Case被害
WITNESSEDPerson→Case目击
CONFESSED_TOPerson→Case供述
SUSPECTED_OFPerson→Case涉嫌
INVOLVED_INPerson→Case涉案关联
OWNSPerson→Evidence拥有物品
DISCOVEREDPerson→Evidence发现证据
LEFT_BEHINDPerson→Evidence留下线索
USEDPerson→Evidence使用物品
BOUGHT_STOLENPerson→Evidence购买赃物
BELONGS_TOPerson→Organization隶属组织
CONTROLSPerson→Organization控制组织
CLUE_TOEvidence→Case线索指向
WEAPON_OFEvidence→Case凶器
LOOT_OFEvidence→Case赃物
LED_TOCase→Case引出案件
LINKED_TOCase→Case案件关联
PART_OFCase→Case系列案
HAPPENED_ATCase→Location发生地点
INVOLVES_ORGCase→Organization涉及组织
DIED_ATPerson→Location死亡地点
WENT_TOPerson→Location前往地点
TRAPPED_INPerson→Location被困地点
INJURED_ATPerson→Location受伤地点
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐