带权限和时间的多跳检索
图检索通常先从查询识别种子实体,再沿允许关系扩展邻居。无限扩展会把高度节点的无关关系全部带入上下文;设置关系类型、方向、跳数、时间、租户和候选预算,才能让结果可解释。
python
edges = [
('A','supplies','B','t1','s1'),
('B','supplies','C','t1','s2'),
('C','supplies','A','t1','s3'),
('B','supplies','D','t2','s4'),
]
def paths(start, tenant, max_hops):
frontier = [(start, [], {start})]
out = []
for _ in range(max_hops):
following = []
for node, path, seen in frontier:
for src,rel,dst,owner,source in edges:
if src==node and rel=='supplies' and owner==tenant and dst not in seen:
next_path = path+[(src,rel,dst,source)]
out.append(next_path)
following.append((dst,next_path,seen|{dst}))
frontier = following
return out
result = paths('A','t1',3)
assert [p[-1][2] for p in result] == ['B','C']
assert [e[3] for e in result[-1]] == ['s1','s2']
print(result)按路径记录seen避免环,同时允许别的路径访问同一节点;全局visited会更省资源,却可能抹掉替代证据路径。过滤在每次扩展执行,D不能因为种子B可见就变得可见。这里未建时间字段,生产扩展要对每条边验证适用时间,不能只验证终点。
“甲供应乙,乙供应丙”可以回答甲与丙之间有两跳供应链,却不能推出甲直接供应丙,也不能推出任意货物都沿链运输。关系是否可传递由领域定义,不由图的可达性决定。路径中的每条边都要带出处,再回查原文是否支持断言。
高出度节点可按查询相关性与关系权威性裁剪;PageRank衡量图结构中心性,不等于事实可信。Cypher或SPARQL适合结构化查询,但模型生成查询必须限制只读、超时与结果量,用户权限仍在数据库/服务端执行。
向量种子检索漏掉实体时图遍历也救不回;别名词法检索、语义检索和澄清问题可互补。不要用整张图的可视化效果证明问答质量。
练习
将最大跳数改为1,只允许返回B。再从C起步验证有环仍能终止,并保留路径出处。
完成后查看本章答案。
下一章:局部检索、社区摘要与更新成本。
下一步在原文到社区的完整实验为每条边加入有效期,用SQL筛出允许子图,再验证过期中间边不能继续连通路径。这里的跳数与权限练习是该实验的前置。