第 8 章 · 02 图数据库与 RDF 三元组库


第 8 章 · 02 图数据库与 RDF 三元组库

本节摘要:向量之外,polyglot 存储还有两翼。graph_store/(11 个文件)统一了 4 种属性图数据库——Neo4j、FalkorDB、Apache AGE、Amazon Neptune(amazon_neptune.py 约 1800 行,IAM 签名认证是四库中最重的实现);triplet_store/(15 个文件)统一了 RDF 三元组库——内嵌零依赖的 Oxigraph,加上 Blazegraph、Jena、RDF4J(另有 Anzo 共 5 个后端)。本节拆两条分发链与各自的管理器体系,讨论属性图 LPG 与 RDF 语义网的选型,并说明:正是 RDF 库让 Semantica 真正"语义网兼容"。

内容来源:原项目源码 semantica/graph_store/graph_store.pyneo4j_store.pyamazon_neptune.pyquery_sanitize.pysemantica/triplet_store/triplet_store.pyoxigraph_store.pyquery_engine.pybulk_loader.pysparql_escaping.py

⚠️ 注意:图库与三元组库是两个独立模块、两套接口,不能互相顶替——属性图查 Cypher 走 graph_store,SPARQL 走 triplet_store;同一份知识图谱若要两边都落,得靠第 9 章 export 模块做格式转换,而不是指望某个"万能后端"。

学习目标

阅读完本节,你应当能够:

  1. 说出 GraphStore 的 4 个后端与分发逻辑,以及四个管理器(Node/Relationship/Query/Analytics)的分工。
  2. 描述 Amazon Neptune 后端的特殊之处:IAM SigV4 认证、Bolt 协议跑 OpenCypher、自动重试与 token 刷新。
  3. 背出 TripletStore.SUPPORTED_BACKENDS 的 5 个名字,理解 Oxigraph"内嵌零依赖"意味着什么。
  4. 说出 SKOS 概念如何被 add_skos_concept 翻译成标准三元组。
  5. 用"要不要与语义网生态互通"来判断该选 LPG 图库还是 RDF 三元组库。

一、graph_store:4 种图库一条分发链

GraphStore 门面(graph_store.py:525)的 docstring 只承诺 Neo4j 与 FalkorDB,实际分发链覆盖四家(graph_store.py:564-596):

566 if self.backend == "neo4j": 568 from .neo4j_store import Neo4jStore 569 neo4j_config = graph_store_config.get_neo4j_config() 570 neo4j_config.update(self.config) 571 self._store_backend = Neo4jStore(**neo4j_config) 573 elif self.backend == "falkordb": 575 from .falkordb_store import FalkorDBStore ... 580 elif self.backend == "neptune" or self.backend == "amazon_neptune": 582 from .amazon_neptune import AmazonNeptuneStore ... 587 elif self.backend == "age" or self.backend == "apache_age": 589 from .age_store import ApacheAgeStore ... 594 else: 594 raise ValidationError(f"Unknown backend: {self.backend}")

三个细节:后端名支持别名neptune/amazon_neptuneage/apache_age);默认值取自 graph_store_config.get("default_backend", "neo4j")(542-546 行);每家先从 config 模块取默认配置再被调用方覆盖(569-570 行的 merge 顺序)。四个后端文件体量都不小——neo4j_store.py 1066 行、falkordb_store.py 1025 行、age_store.py 1343 行、amazon_neptune.py 1793 行:图库适配的复杂度远高于向量库,因为除增删查外还要对齐索引、批量导入与分析接口。Apache AGE 值得一提:它是 PostgreSQL 的开源扩展,图数据直接住在你已有的 PG 里——与 01 节 pgvector 是"复用 PG"思路在图世界的镜像。

二、门面四管理器:对操作面的正交拆分

GraphStore 把操作拆给四个内聚的管理器(graph_store.py):

  • NodeManager(44 行):create/create_batch/get/update/delete,节点 CRUD 与批量;
  • RelationshipManager(159 行):create/get/delete,边操作;
  • QueryEngine(240 行):execute(255 行)跑 Cypher,自带查询缓存——_generate_cache_key(289 行)把查询串参数化成 key,enable_cache/disable_cache/clear_cache(300-311 行)三个开关随手控制;
  • GraphAnalytics(313 行):shortest_path(326 行)、get_neighbors(351 行)、degree_centrality(376 行)、connected_components(432 行)——第 3 章图分析调用正是这层。

GraphManager(482 行)再包一层 get_stats/create_index 给统计与索引入口。安全闸在门外:query_sanitize.py(仅 32 行)专给查询入参消毒。这个"门面只做分发、管理器按对象正交拆分、后端各自实现"的结构,是读任何 *_store.py 前都该装进脑子的地图。

三、Amazon Neptune:四库中最重的适配

amazon_neptune.py 模块头(1-15 行)点明两个特殊性:

IAM authentication using AWS SigV4 signing via AuthManager / OpenCypher query language support via Bolt protocol

Neptune 复用 Neo4j 的 Bolt 驱动,但连接前要 AWS SigV4 签名——模块内置 NeptuneAuthTokenManager(IAM 认证处理器),Key Features 列表写明"automatic retry with backoff / connection recovery / token refresh"(自动重试退避、连接恢复、token 刷新)。用起来是纯配置问题(模块 docstring 示例):

>>> store = AmazonNeptuneStore( ... endpoint="your-neptune-cluster.region.neptune.amazonaws.com", ... port=8182, region="us-east-1", iam_auth=True) >>> store.connect() >>> node_id = store.create_node(labels=["Person"], properties={"name": "Alice"})

存在意义与 pgvector 同构:把第 3 章 GraphBuilder 产出的图谱原样搬进云托管图数据库,业务代码零改动。代价是适配层最重——1793 行里大半在处理认证、重试与连接生命周期。

四、triplet_store:RDF 世界的五个名字

TripletStore(triplet_store.py:40)的官方清单比图库还多一个:

48 SUPPORTED_BACKENDS = {"blazegraph", "jena", "rdf4j", "anzo", "oxigraph"} 51 NAMED_GRAPH_CAPABLE_BACKENDS = { 52 "blazegraph", "rdf4j", "anzo", "oxigraph", 53 }

主推四家之外还有 Anzo;NAMED_GRAPH_CAPABLE_BACKENDS 记录谁支持命名图(RDF 的"图中之图",同一库内做数据集隔离——多租户/多项目的 RDF 版答案)。_initialize_store_backend(96-163 行)里,服务型后端都有默认端点:Blazegraph http://localhost:9999/blazegraph、Jena http://localhost:3030/ds、RDF4J http://localhost:8080/rdf4j-serverendpoint 参数可覆盖。而 Oxigraph 不需要端点——它是内嵌的:

69 self.store = self._oxigraph.Store(store_path)

一行就是全部魔法。Oxigraph 是 Rust 实现的嵌入式 RDF 库(Rust 编译的 Python 绑定),像 SQLite 之于 MySQL——pip install 完直接在进程内起一个支持 SPARQL 的三元组库,store_path 给了就落盘、不给就内存,失败时 71-74 行还会报出初始化位置。这是"无 key 跑通"承诺在 RDF 侧的答案:不装任何服务器,也能拥有一个真·语义网数据库

门面层的能力(triplet_store.py):store(165 行,写入时 _resolve_iri 把本地名解析成 IRI)、add_triplet/add_triplets/get_triplets/delete_triplet/update_triplet(345-450 行一组标准 CRUD)、execute_query(450 行跑 SPARQL)、compute_delta(656 行,对比两组 SPARQL 结果算三元组级增量——审计与同步都吃这个)。构造时还挂上两个组件:QueryEngine(query_engine.py,571 行,查询构造与执行)与 BulkLoader(bulk_loader.py,370 行,批量装载)。防御与效率各有一位专职:sparql_escaping.py(195 行,SPARQL 注入防护——与图库的 query_sanitize 同一思路)与 construct_templates.py(828 行,预置常用 SPARQL 构造模板)。

五、SKOS:三元组库的原生词汇表

RDF 库最区别于图库的一点:它对 W3C 标准词汇表是"母语"。add_skos_concept(triplet_store.py:504-560)把一个 SKOS 概念翻译成一组标准三元组:

548 triplets: List[Triplet] = [ 549 # Scheme declaration 550 Triplet(scheme_uri, RDF_TYPE, f"{SKOS}ConceptScheme"), 551 # Concept core 552 Triplet(concept_uri, RDF_TYPE, f"{SKOS}Concept"), 553 Triplet(concept_uri, f"{SKOS}inScheme", scheme_uri), 554 Triplet(concept_uri, f"{SKOS}prefLabel", pref_label), 555 ] 556 for lbl in (alt_labels or []): 557 triplets.append(Triplet(concept_uri, f"{SKOS}altLabel", lbl)) 558 for uri in (broader or []): 558 triplets.append(Triplet(concept_uri, f"{SKOS}broader", uri))

签名里的 alt_labels/broader/narrower/related/definition/notation 逐个落成 skos: 谓词,ConceptScheme 不存在还会自动建(544-547 行 docstring 声明)。"同义词"(altLabel)、"上下位"(broader/narrower)、"关联"(related)全部变成可 SPARQL 查询的数据——get_skos_concepts(570 行)读回,第 9 章本体工程的 SKOS 词表就落在这里。

六、LPG 还是 RDF:一张选型表

属性图(LPG)与 RDF 是知识图谱两大建模阵营,Semantica 两个都接:

维度 graph_store(LPG) triplet_store(RDF)
模型 节点/边都带属性 三元组 s-p-o,边属性需物化或 RDF-star
查询语言 Cypher / OpenCypher SPARQL
标准词汇 无强制,标签随意 OWL 本体、SKOS 词表、SHACL 约束原生兼容
工具生态 Neo4j Browser、图可视化 Protégé、语义网推理机、链接数据平台
典型场景 实时图应用、GraphRAG 多跳、图算法 数据集成、跨组织互通、受控词表、合规发布
起步成本 起 Neo4j/FalkorDB 服务 Oxigraph 零依赖内嵌,一行起库

选型心法:图给你自己用、要性能与灵活标签——LPG;图要发给别的系统/组织用、要对齐 W3C 标准——RDF。Semantica 的答案是不必二选一:第 3 章的 KnowledgeGraph 是中立数据结构,第 9 章 export 既能出 LPG(Cypher/GraphML)也能出 RDF(Turtle/JSON-LD/N-Triples),落库时按场景各取所需。

💡 装配要点:两条对称的分发链——GraphStore._initialize_store_backend(graph_store.py:564)与 TripletStore._initialize_store_backend(triplet_store.py:96)都是"config 读默认→按名 import→合并配置→实例化"。差异在生态位:图库四管理器对齐 Cypher 世界;三元组库的 QueryEngine/BulkLoader/construct_templates/sparql_escaping 对齐 SPARQL 世界。Oxigraph 用第 69 行那一行 Store(store_path) 兜住"语义网兼容"的最低门槛。

本节要点回顾

  1. 4 图库:Neo4j(默认)、FalkorDB、Apache AGE(PG 扩展)、Amazon Neptune(别名 neptune),分发在 graph_store.py:564-596,未知名抛 ValidationError
  2. 门面四管理器:Node/Relationship/QueryEngine(带缓存开关)/GraphAnalytics(最短路、邻居、度中心性、连通分量);入参过 query_sanitize。
  3. Neptune 特殊性:SigV4 IAM 签名 + Bolt 跑 OpenCypher + 重试退避与 token 刷新,约 1800 行是最大的单店适配。
  4. 5 RDF 后端:blazegraph/jena/rdf4j/anzo/oxigraph(triplet_store.py:48);前四家是 HTTP 服务带默认端点,Oxigraph 内嵌零依赖、一行 Store(store_path) 起库;命名图能力按后端声明。
  5. SKOS 原生支持add_skos_concept 把概念/同义词/层级/关联翻成 skos: 三元组,语义网兼容落到数据层。
  6. LPG vs RDF:性能与灵活选 LPG,互通与标准选 RDF;统一中间表示 + export 转换让你不必二选一。

下一节:02 节看到了"一行参数切换后端"的现象,03 节拆它的机关——MethodRegistryPluginRegistry:注册表模式如何让多后端即插即用,又如何成为你自己写扩展的正规入口。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U