kuzu

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 是关系表,字段都是提前定义好的列。