Kuzu 下载安装 #
Kuzu 和 Neo4j 最大区别是:Kuzu 通常不需要启动一个独立数据库服务,它是嵌入到程序进程里的数据库。官方也把它定位为 embedded graph database,支持 CLI、Python、Go 等方式使用,见 Kuzu 安装文档。
学习时可以选两条路:
# Python 学习最简单 python -m pip install kuzu
# Go 项目中使用 go get github.com/kuzudb/go-kuzu@v0.11.3
但项目里不是最新官方版本,而是锁定在:
github.com/kuzudb/go-kuzu v0.10.0
项目还带了本地动态库:kuzu_shared.dll。
使用 #
数据库连接 #
database, err := kuzu.OpenDatabase(dbPathLocal, kuzu.DefaultSystemConfig())
conn, err := kuzu.OpenConnection(database)
数据结构 #
Kuzu 不是 Neo4j 那种“弱 schema 的 label + properties”。Kuzu 官方文档说它要求预定义 schema,使用 CREATE NODE TABLE 和 CREATE REL TABLE 定义节点表、关系表、属性类型和主键,见 Create table 文档。
所以你可以这样理解:
| Neo4j 概念 | Kuzu 中对应 | 项目中例子 |
|---|---|---|
| 节点标签 Label | Node Table 名称 | Person、Evidence、Account、Group |
| 关系类型 Relationship Type | Rel Table 名称 | HasEvidence、HasAccount、ContactWith、HasRelation |
| 属性 Property | 表字段 / 列 | personName、eid、virtualId、remark |
| 节点唯一标识 | Node Table 主键 | 项目里统一用 elementId |
| 图关系方向 | FROM … TO … | FROM Person TO Evidence |
节点表:
| 节点表 | 相当于标签 | 主键 | 主要属性 |
|---|---|---|---|
| Person | 人员节点 | elementId | personName、aiSummary、remark、position |
| Evidence | 检材节点 | elementId | eid、position |
| Account | 账号节点 | elementId | virtualId、nickName、fromApp、phoneNumber、trueName、caseRelatedScore |
| Group | 群组节点 | elementId | groupId、groupName、fromApp、memberCount、owerAccount、owerName |
关系表:
| 关系表 | 方向 | 含义 | 主要属性 |
|---|---|---|---|
| HasEvidence | Person -> Evidence | 人员拥有检材 | personName、eid |
| HasAccount | Evidence -> Account | 检材中发现账号 | eid、tid、userId、nickName |
| ContactWith | Account -> Account、Account -> Group | 账号和账号/群发生联系 | eid、tid、pid、dataType、chatCount、transCount、latestMessageTime |
| HasRelation | Person -> Person | 人员之间的关系 | aiSummary、caseRelatedScore |
这里最重要的是:Person、Evidence、Account、Group 不是随便贴的标签,而是 Kuzu 的节点表;属性必须提前声明类型。
项目里的图大概是:
graph LR
Person["Person 人员"] -->|HasEvidence| Evidence["Evidence 检材"]
Evidence -->|HasAccount| Account["Account 账号"]
Account -->|ContactWith| Account2["Account 账号"]
Account -->|ContactWith| Group["Group 群组"]
Person -->|HasRelation| Person2["Person 人员"]
4. 增删查改 建表:
CREATE NODE TABLE Person(
elementId STRING,
personName STRING,
remark STRING,
PRIMARY KEY (elementId)
);
CREATE NODE TABLE Evidence(
elementId STRING,
eid INT64,
PRIMARY KEY (elementId)
);
CREATE REL TABLE HasEvidence(
FROM Person TO Evidence,
personName STRING,
eid INT64
);
新增或更新节点,项目里大量使用 MERGE + SET,官方也说明 MERGE 类似“存在则匹配,不存在则创建”,见 MERGE 文档。
MERGE (p:Person {elementId: "personName-张三"})
SET p.personName = "张三",
p.remark = "重点人员";
新增关系:
MATCH (p:Person {personName: "张三"})
MATCH (e:Evidence {eid: 1001})
MERGE (p)-[r:HasEvidence]->(e)
SET r.personName = "张三",
r.eid = 1001;
查询:
MATCH (p:Person)-[:HasEvidence]->(e:Evidence)-[:HasAccount]->(a:Account)
RETURN p.personName, e.eid, a.virtualId, a.nickName;
查询账号联系:
MATCH (a:Account)-[cw:ContactWith]->(b:Account)
RETURN a.virtualId, b.virtualId, cw.dataType, cw.chatCount, cw.latestMessageTime;
修改:
MATCH (a:Account {elementId: "account-wx001"})
SET a.remark = "重点账号",
a.caseRelatedScore = 90;
删除节点:
MATCH (n)
WHERE n.elementId = $elementId
DETACH DELETE n;
删除某个任务 tid 的关系:
MATCH ()-[r:ContactWith]->()
WHERE r.tid = 123
DELETE r;
5. 项目中的应用 项目通过同一个 GraphDB 接口屏蔽 Neo4j 和 Kuzu 的差异。桌面端:
return kuzu.NewClient(), nil
服务端则返回 Neo4j client。也就是说,上层业务调用“创建人员-检材关系、创建账号-检材关系、创建账号联系关系、查询图谱概览、删除图谱节点”等接口时,不需要太关心底层是 Neo4j 还是 Kuzu。
6. 底层存储怎么理解 不要把 Kuzu 简单想成“每个节点一个链表”或“二维邻接矩阵”。官方文档介绍 Kuzu 使用列式磁盘存储、CSR 风格的邻接列表/连接索引,并支持向量化查询执行,见 Kuzu 文档首页。
可以这样类比:
节点表 Person / Account -> 类似列式表,属性按列存
关系表 ContactWith -> 存 FROM/TO 节点之间的边和边属性
遍历 (a)-[:R]->(b) -> 利用关系表的邻接结构做图连接
所以 Kuzu 更像:
强类型节点表 + 强类型关系表 + 邻接索引 + 列式存储
而不是:
纯链表
二维矩阵
随便贴 label 的无 schema 图
Kuzu 是“表结构化的属性图数据库”;项目里的 Person、Account 这些不是普通标签,而是节点表,HasEvidence、ContactWith 是关系表,字段都是提前定义好的列。