添加 图数据库结构设计

This commit is contained in:
2026-04-08 11:48:07 +00:00
parent d06472394b
commit d5a90cc1b4

254
图数据库结构设计 Normal file
View File

@ -0,0 +1,254 @@
以下是完整的 Neo4j 图数据库结构设计,针对 OpenClaw 对话记忆场景优化,边上带完整时间戳和元数据:
1. 节点Node设计
实体节点Entity
(:Entity {
name: string, // 实体名称(唯一标识)
type: string, // 类型concept | technology | person | project | decision
created_at: datetime, // 首次出现时间
updated_at: datetime, // 最后更新时间
mention_count: int // 被提及次数(用于权重)
})
会话节点Session
(:Session {
session_id: string, // 会话唯一ID如 20260408-a7f3
created_at: datetime, // 会话开始时间
summary: string, // 会话摘要(可选)
status: string // active | archived | compacted
})
2. 关系Edge设计
核心关系RELATES
所有对话关系统一使用 RELATES 类型,属性承载时间戳和元数据:
(source:Entity)-[:RELATES {
// 基础关系属性
type: string, // 关系类型uses | implements | depends_on | rejects | prefers | leads_to | contradicts
// 时间戳(核心)
created_at: datetime, // 关系创建时间(精确到秒)
updated_at: datetime, // 最后更新时间(纠错时更新)
// 来源追踪
session_id: string, // 所属会话ID
turn_id: int, // 轮次序号(该会话中的第几轮)
// 角色标记
role: string, // "user" | "assistant" | "system"
// 内容快照
context_snippet: string, // 原始文本片段前100字符
// 状态管理
status: string, // active | deleted | archived | superseded被取代
confidence: float, // 置信度0.0-1.0,提取算法给出)
// 时序检索辅助
date_bucket: string // 日期分区2026-04-08用于快速范围查询
}]->(target:Entity)
时序链NEXT- 可选
用于严格保持对话顺序:
(:Entity)-[:NEXT {
session_id: string,
created_at: datetime
}]->(:Entity)
3. 索引与约束
// 实体唯一性约束
CREATE CONSTRAINT entity_name_constraint IF NOT EXISTS
FOR (e:Entity) REQUIRE e.name IS UNIQUE;
// 会话唯一性约束
CREATE CONSTRAINT session_id_constraint IF NOT EXISTS
FOR (s:Session) REQUIRE s.session_id IS UNIQUE;
// 关系查询索引(按时间戳检索关键)
CREATE INDEX rel_created_at IF NOT EXISTS
FOR ()-[r:RELATES]-() ON r.created_at;
CREATE INDEX rel_session_id IF NOT EXISTS
FOR ()-[r:RELATES]-() ON r.session_id;
CREATE INDEX rel_type IF NOT EXISTS
FOR ()-[r:RELATES]-() ON r.type;
CREATE INDEX rel_status IF NOT EXISTS
FOR ()-[r:RELATES]-() ON r.status;
CREATE INDEX rel_date_bucket IF NOT EXISTS
FOR ()-[r:RELATES]-() ON r.date_bucket;
// 复合索引(会话+时间)
CREATE INDEX rel_session_time IF NOT EXISTS
FOR ()-[r:RELATES]-() ON (r.session_id, r.created_at);
4. 数据模型示例
插入场景
用户说:"我想用 Neo4j 改造 OpenClaw 的记忆系统,替换掉原来的 SQLite 方案。"
生成的图结构:
// 节点
(:Entity {name: "OpenClaw", type: "project", created_at: now()})
(:Entity {name: "Neo4j", type: "technology", created_at: now()})
(:Entity {name: "SQLite", type: "technology", created_at: now()})
(:Entity {name: "记忆系统改造", type: "decision", created_at: now()})
// 关系(带时间戳)
(OpenClaw)-[:RELATES {
type: "uses",
created_at: datetime("2026-04-08T19:45:00"),
session_id: "20260408-a7f3",
turn_id: 1,
role: "user",
context_snippet: "我想用 Neo4j 改造 OpenClaw...",
status: "active",
confidence: 0.95,
date_bucket: "2026-04-08"
}]->(Neo4j)
(OpenClaw)-[:RELATES {
type: "replaces",
created_at: datetime("2026-04-08T19:45:00"),
session_id: "20260408-a7f3",
turn_id: 1,
role: "user",
context_snippet: "替换掉原来的 SQLite 方案",
status: "active",
confidence: 0.92,
date_bucket: "2026-04-08"
}]->(SQLite)
(记忆系统改造)-[:RELATES {
type: "involves",
created_at: datetime("2026-04-08T19:45:00"),
session_id: "20260408-a7f3",
turn_id: 1,
role: "user",
status: "active",
date_bucket: "2026-04-08"
}]->(OpenClaw)
5. 关键查询模式
A. 时序检索(最新记忆优先)
// 查询实体相关的最新关系(按时间戳倒序)
MATCH (e:Entity {name: $entity_name})-[r:RELATES]-(target:Entity)
WHERE r.status = 'active'
RETURN e, r, target
ORDER BY r.created_at DESC
LIMIT 20
B. 会话范围查询(上下文隔离)
// 仅查询特定会话内的关系
MATCH (s:Entity)-[r:RELATES]->(t:Entity)
WHERE r.session_id = $session_id
RETURN s.name, r.type, t.name, r.created_at
ORDER BY r.turn_id
C. 时间范围查询最近N天
// 利用 date_bucket 或时间戳范围
MATCH (s:Entity)-[r:RELATES]->(t:Entity)
WHERE r.date_bucket >= date().isoDate - duration('P7D') // 最近7天
OR r.created_at >= datetime() - duration('P7D')
RETURN s, r, t
ORDER BY r.created_at DESC
D. 多跳路径查询(关联推理)
// 查询两个实体间的路径(带时间约束)
MATCH path = (start:Entity {name: $start})-[:RELATES*1..3]->(end:Entity {name: $end})
WHERE ALL(r IN relationships(path) WHERE r.status = 'active')
RETURN path,
[r IN relationships(path) | r.created_at] as path_timestamps,
length(path) as hops
ORDER BY path_timestamps[-1] DESC // 按最后关系时间排序
LIMIT 5
E. 纠错更新(软删除)
// 用户更正时,不物理删除,而是标记为 superseded 并创建新关系
MATCH (s:Entity {name: $source})-[r:RELATES {type: $old_relation}]->(t:Entity {name: $target})
WHERE r.status = 'active'
SET r.status = 'superseded',
r.updated_at = datetime(),
r.superseded_by = $new_relation_id // 指向新关系的ID
// 创建新关系(带新的时间戳)
CREATE (s)-[:RELATES {
type: $new_relation,
created_at: datetime(),
session_id: $session_id,
turn_id: $turn_id,
role: $role,
status: 'active',
supersedes: $old_relation_id
}]->(t)
6. 存储过程APOC优化
批量插入(高性能)
// 使用 APOC 批量合并,避免逐条插入开销
CALL apoc.periodic.iterate(
"UNWIND $triples as t RETURN t",
"
MERGE (s:Entity {name: t.source})
ON CREATE SET s.created_at = datetime(), s.type = coalesce(t.source_type, 'unknown')
ON MATCH SET s.updated_at = datetime(), s.mention_count = coalesce(s.mention_count, 0) + 1
MERGE (e:Entity {name: t.target})
ON CREATE SET e.created_at = datetime(), e.type = coalesce(t.target_type, 'unknown')
ON MATCH SET e.updated_at = datetime(), e.mention_count = coalesce(e.mention_count, 0) + 1
CREATE (s)-[r:RELATES {
type: t.relation,
created_at: datetime(),
session_id: t.session_id,
turn_id: t.turn_id,
role: t.role,
status: 'active',
date_bucket: date().isoDate,
confidence: coalesce(t.confidence, 1.0)
}]->(e)
",
{batchSize: 100, params: {triples: $triples}}
)
时序压缩(归档旧关系)
// 将N天前的关系标记为 archived但保留节点
MATCH ()-[r:RELATES]->()
WHERE r.created_at < datetime() - duration('P30D') // 30天前
AND r.status = 'active'
SET r.status = 'archived',
r.archived_at = datetime()
RETURN count(r) as archived_count
7. 与 Bridge API 的映射
API 端点 Cypher 操作 时间戳处理
POST /insert MERGE 节点 + CREATE 关系 datetime() 自动生成
POST /search MATCH 带时间戳排序 返回 r.created_at 等字段
POST /delete SET r.status = 'deleted' 软删除,保留 updated_at
8. 数据保留策略
// 节点保留:永久(实体名词长期有效)
// 关系保留策略:
// - active: 最近30天高频查询
// - archived: 30-90天低频查询需指定时间范围
// - deleted: 逻辑删除保留90天后物理清理APOC 定时任务)
// 物理清理(谨慎操作)
MATCH ()-[r:RELATES]->()
WHERE r.status = 'deleted'
AND r.updated_at < datetime() - duration('P90D')
DELETE r
WITH count(*) as deleted_relations
MATCH (e:Entity)
WHERE NOT (e)-[:RELATES]-() // 无关系的孤立节点
DELETE e
RETURN deleted_relations, count(e) as deleted_orphans
这个设计支持时间旅行查询(查看任意时刻的图状态)、会话隔离(只看当前对话历史)和渐进式遗忘(旧关系归档但不删除),符合 OpenClaw 的增量记忆需求。
}]
)
}]
}]
}]
}]
}]
}]
})
})