知识图谱基础:实体、关系、属性与三元组
这一章,我们聊聊知识图谱最核心的底层概念。说白了,就是理解知识图谱到底用什么方式组织信息。我在做药靶关联图谱项目的时候,发现很多团队成员不理解「三元组」这个基础,结果数据一多,查询就乱了。所以这一章会把地基打牢。
实体、关系、属性——知识图谱的“三原色”
知识图谱里,信息被拆成三种基本元素。我个人习惯把它们比作乐高积木的三种基础块。
- 实体:现实世界中可被区分的事物。比如“阿司匹林”、“COX-1蛋白”、“头痛”。
- 关系:实体之间如何连接。比如“靶向”、“治疗”、“抑制”。
- 属性:描述实体的特征。比如“分子量=180.16”、“半衰期=3小时”。
举个例子,在药物知识图谱里,阿司匹林 是一个实体,抑制 是关系,COX-1 是另一个实体。它们合起来就是一个完整的知识单位。
我的经验:做图谱设计时,先画实体和关系,再补属性。不要一开始就纠结属性的粒度。我曾经因为把“给药途径”设成关系还是属性,跟团队争论了三天。后来发现,让它保持为属性更灵活,因为同一药物可以有多个给药途径,而这种信息不需要建立独立的关系链接。
三元组——知识的最小单元
知识图谱有个经典结构:(头实体, 关系, 尾实体)。这就是三元组。它像一个“原子”,不可再分。
# 三元组示例
(阿司匹林, 靶向, COX-1)
(COX-1, 位于, 血小板)
(血小板, 参与, 凝血过程)
你想想看,所有复杂的知识网络,都是这些三元组拼接出来的。在数据库里,三元组的存储格式一般长这样:
# 标准RDF格式(Turtle语法)
@prefix drug: <http://example.org/drug/> .
@prefix target: <http://example.org/target/> .
drug:aspirin drug:targets target:cox1 .
drug:aspirin drug:hasSmiles "CC(=O)OC1=CC=CC=C1C(=O)O" .
drug:aspirin rdf:type drug:Antipyretic .
我建议用三元组存储时,每条数据都要能独立解释。如果(X, 关系, Y)去掉X或Y就说不通,那这个三元组设计就有问题。
图结构与逻辑结构
这块容易混淆,我分开说。
图结构
知识图谱的图结构,是物理存储的样子。节点存实体,边存关系。每个节点可以有多条边连接其他节点。这跟社交网络一样,一个药物节点可能连着靶点、疾病、副作用等。
逻辑结构
逻辑结构是人对知识的分类方式,比如schema、本体。它定义了一组规则:哪些实体可以有什么关系,每个实体必须有哪些属性。
举个例子,逻辑结构里会规定:
- 药物必须至少有一个靶点
- 药物可以有多个适应症
- 靶点一般是蛋白质或基因
图结构是“数据怎么放”,逻辑结构是“数据怎么用”。
这里有一张我画的图,帮你快速对比理解:
与关系数据库、NoSQL的区别
我经常被问到:知识图谱不就是个带关系的图吗?传统数据库也能存关系啊。嗯,这里要注意,区别还真不小。
| 维度 | 关系数据库(RDBMS) | NoSQL(文档/键值) | 知识图谱 |
|---|---|---|---|
| 数据模型 | 二维表,行和列 | JSON文档、键值对 | 图,节点+边+属性 |
| 关联处理 | 通过JOIN连接表 | 嵌套文档或手动引用 | 直接走边,邻接表遍历 |
| 查询深度 | JOIN层数>3时性能骤降 | 不适合深度关联 | 轻松处理5层以上关联 |
| schema | 强约束,需预先定义 | 弱约束,可动态扩展 | 可松可紧,但通常有本体规范 |
| 典型场景 | 事务、报表、CRM | 日志、缓存、用户会话 | 知识推理、关联发现、问答 |
| 药物研发用例 | 临床试验数据录入 | 化合物结构缓存 | 靶点-药物-疾病-通路关联推理 |
拿药物研发场景举个例子。如果我要查“所有与阿司匹林共享靶点且治疗头痛的药物”,在关系数据库里,你可能需要写:
SELECT d2.drug_name
FROM drug_target dt1
JOIN drug_target dt2 ON dt1.target_id = dt2.target_id
JOIN drug_indication di ON dt2.drug_id = di.drug_id
JOIN drug d2 ON dt2.drug_id = d2.drug_id
WHERE dt1.drug_id = 'aspirin'
AND di.indication = 'headache'
AND dt1.drug_id != dt2.drug_id;
但在知识图谱里,一条Cypher查询就搞定:
MATCH (d:Drug {name: '阿司匹林'})-[:靶向]->(t:Target)<-[:靶向]-(other:Drug),
(other)-[:治疗]->(dis:Disease {name: '头痛'})
RETURN DISTINCT other.name
你想想看,三表JOIN vs 一条路径匹配,哪个更直观?
避坑提醒:别以为知识图谱万能。在我早期的项目中,曾尝试用图谱做实时交易系统,结果发现图数据库的事务写入性能远不如关系数据库。它们各有各的战场。
说白了,关系数据库适合“我知道我要查什么,数据关系稳定”的场景。NoSQL适合“我需要快速读写简单结构”的场景。知识图谱则擅长“我事先不知道关联方式,但我要探索关联”的场景。做药物研发,三类数据库通常会一起用。
本节要点总结
- 实体是图谱中的“节点”,关系是“边”,属性是节点的“细节描述”。
- 三元组是知识的最小原子:
(头实体, 关系, 尾实体)。 - 图结构解决“数据怎么存”,逻辑结构解决“数据怎么解释”。
- 知识图谱的核心优势:多跳关联查询、灵活扩展、语义推理。
- 选型时,别用图谱做它不擅长的事——比如高频写入和事务一致性强需求。