Show HN:Minigraf — 一个用 Rust 编写的嵌入式双时态图数据库

Hacker News Top 工具

摘要

Minigraf 是一个用 Rust 编写的嵌入式、单文件双时态图数据库,提供 Datalog 查询、基于事务时间和有效时间的时间旅行、窗口函数以及预处理语句——目标是成为图数据库领域的「SQLite」,面向 AI 智能体、移动应用和浏览器场景。

这是我上一次尝试构建时态图数据库的后续项目(<a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=23455516">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=23455516</a>)。这个项目延续了前作的理念,但不再依赖另一个数据库来提供存储、事务和查询引擎。Minigraf 完全自包含,以 library crate 的形式打包,可以嵌入到你的应用中,并支持完整的双时态特性。
查看原文
查看缓存全文

缓存时间: 2026/10/05 17:44

project-minigraf/minigraf

来源:https://github.com/project-minigraf/minigraf

Minigraf

crates.io (https://crates.io/crates/minigraf) docs.rs (https://docs.rs/minigraf) 构建状态 (https://github.com/project-minigraf/minigraf/actions/workflows/rust.yml) Clippy 状态 (https://github.com/project-minigraf/minigraf/actions/workflows/rust-clippy.yml) 测试覆盖率 (https://codecov.io/gh/project-minigraf/minigraf) 许可证:MIT OR Apache-2.0 (https://github.com/project-minigraf/minigraf#license) Rust 版本 (https://doc.rust-lang.org/edition-guide/rust-2024/index.html) MSRV

面向 AI agent、移动应用和浏览器的嵌入式图内存 —— 双时态图数据库领域的 SQLite

一个极小、自包含的图数据库,支持 Datalog 查询 和 双时态时间旅行。可以把它想成 SQLite,但专门用于带完整历史的关联数据。

在浏览器中试试——无需安装 → (https://minigraf-playground.vercel.app/)

在可视化工具中观看时间旅行 → (https://project-minigraf.github.io/minigraf-visualizer/#sample=careers&tx=7&e=:alice&view=map) 拖动事务时间和有效时间,观察图的变化。

愿景

Minigraf 是一个单文件嵌入式图数据库,让你可以:

  • ✅ 用 Datalog 查询关系 — 递归规则,自然的图遍历
  • ✅ 在历史中时间旅行 — 双时态查询(事务时间 + 有效时间)
  • ✅ 窗口函数 — 在 :find 子句中使用 sum/count/min/max/avg/rank/row-number :over (partition-by ... :order-by ...)
  • ✅ 预编译语句 — 使用 $slot 绑定占位符,解析 + 规划一次,执行数千次
  • ✅ 随处嵌入 — 原生、WASM、移动端、物联网——只需一个 .graph 文件
  • ✅ 零配置 — 只需 Minigraf::open("data.graph") 就能开始

状态:详见 ROADMAP.md,了解规划中的工作和当前方向。

为什么选 Datalog?

对于图数据,Datalog 在根本上优于 SQL 类语言:

  1. 天生递归 — 多跳遍历是自然的表达方式,而非事后补丁
  2. 实现更简单 — 更小的规范 = 更可靠,更快走向生产
  3. 非常适合时间维度 — 时间只是关系中的另一个维度
  4. 已被大规模验证 — 40 多年的研究与生产应用(Datomic、XTDB)
  5. 图原生 — 事实(实体-属性-值)本质上就是边
  6. 对 LLM 友好 — 小而统一的语法([?e :attr ?v] 模式,无 JOIN 变体,无子查询嵌套),AI 编程助手只需几个示例就能正确生成;整个语言可以用一个 system prompt 装下

安装

[dependencies]
minigraf = "2.0.2"

或者通过 cargo:

cargo add minigraf

需要 Rust 1.89 或更高版本(在 Cargo.toml 中设置的最低支持版本)。

已知问题

当前版本中的 bug,包括受影响的版本、规避方法和修复版本,列在置顶的 当前版本已知问题 (https://github.com/project-minigraf/minigraf/issues/421) issue 中。v2.x 中最重要的一条:

  • 同一实体的同一属性的两个值在一次 transact 中写入(或一次 retract 中撤销)时,可能读回为一个值 (#371 (https://github.com/project-minigraf/minigraf/issues/371))。请为多值属性的每个值分别调用写入或撤销。修复会更改文件格式,并随 v3.0.0 发布。

v2.x 将在 v3.0.0 发布后继续获得 12 个月的数据完整性和安全修复。参见支持策略。

快速开始

use minigraf::{Minigraf, OpenOptions};

// 打开或创建文件型数据库
let db = OpenOptions::new().path("myapp.graph").open()?;

// 写入事实
db.execute(r#"(transact [[:alice :person/name "Alice"]
                         [:alice :person/age 30]
                         [:alice :friend :bob]
                         [:bob :person/name "Bob"]])"#)?;

// 用 Datalog 查询
let results = db.execute(r#"
    (query [:find ?friend-name
            :where [:alice :friend ?friend]
                   [?friend :person/name ?friend-name]])
"#)?;

// 显式事务——要么全部成功,要么全部回滚
let mut tx = db.begin_write()?;
tx.execute(r#"(transact [[:alice :person/age 31]])"#)?;
tx.commit()?;

// 时间旅行——查询过去某个事务计数时的状态
db.execute("(query [:find ?age :as-of 1 :where [:alice :person/age ?age]])")?;

// 递归规则——传递可达性
db.execute(r#"(rule [(reachable ?a ?b) [?a :friend ?b]])
              (rule [(reachable ?a ?b) [?a :friend ?m] (reachable ?m ?b)])"#)?;

// 预编译语句——解析 + 规划一次,执行多次
use minigraf::BindValue;
let pq = db.prepare("(query [:find ?name :as-of $tx :where [$entity :person/name ?name]])")?;
let r1 = pq.execute(&[("tx", BindValue::TxCount(1)), ("entity", BindValue::Entity(alice_id))])?;
let r2 = pq.execute(&[("tx", BindValue::TxCount(2)), ("entity", BindValue::Entity(bob_id))])?;
cargo run          # 交互式 Datalog REPL
cargo test         # 运行 1212 个测试
cargo run < demos/demo_recursive.txt   # 递归规则演示

演示

在 github.com/adityamukho/temporal_reasoning (https://github.com/adityamukho/temporal_reasoning) 可以看到 Minigraf 实现时间推理的完整示例——一个使用 Minigraf 双时态模型来存储、修正和审计信念的 AI agent。

时间旅行可视化工具 (https://project-minigraf.github.io/minigraf-visualizer/) 在你的浏览器中运行 Minigraf,并绘制其历史。逐步遍历事务、移动有效时间游标,在双时态地图上查看每个事实版本。它也支持打开 .graph 文件。例如,查看一条记录错误后被更正的薪水 (https://project-minigraf.github.io/minigraf-visualizer/#sample=careers&tx=7&e=:alice&view=map)。

完整语法参见 Datalog 参考文档 (https://github.com/project-minigraf/minigraf/wiki/Datalog-Reference) wiki 页面。

为什么选择 Minigraf?

没有其他数据库能提供这样的组合:

特性MinigrafXTDBCozoNeo4jSQLite
查询语言DatalogDatalogDatalogCypherSQL
单文件✅ 是❌ 否❌ 否❌ 否✅ 是
双时态✅ 是✅ 是⚠️ 时间旅行❌ 否❌ 否
嵌入式✅ 是✅ 是✅ 是❌ 否✅ 是
图原生✅ 是✅ 是✅ 是✅ 是❌ 否
Rust✅ 是❌ Clojure✅ 是❌ Java❌ C
WASM 就绪✅ 是(浏览器 + WASI)❌ 否⚠️ 有限支持❌ 否✅ 是

平台支持

平台层级包安装方式
Rust(原生)1crates.io 上的 minigrafcargo add minigraf
Python1PyPI 上的 minigrafpip install minigraf
浏览器 WASM2(实验性)npm 上的 @minigraf/browsernpm install @minigraf/browser
WASI2(实验性)npm 上的 @minigraf/wasinpm install @minigraf/wasi
Node.js2(实验性)npm 上的 minigrafnpm install minigraf
Java/JVM2(实验性)Maven Central 上的 io.github.project-minigraf:minigraf-jvm参见 wiki (https://github.com/project-minigraf/minigraf/wiki/Use-Cases)
Android2(实验性)Maven Central 上的 io.github.project-minigraf:minigraf-android(.aar)参见 wiki (https://github.com/project-minigraf/minigraf/wiki/Use-Cases)
iOS / macOS2(实验性)通过 Swift Package Manager(minigraf-swift (https://github.com/project-minigraf/minigraf-swift))分发的 .xcframework参见 wiki (https://github.com/project-minigraf/minigraf/wiki/Use-Cases)
C / FFI2(实验性)minigraf-c releases (https://github.com/project-minigraf/minigraf-c/releases) 上的头文件 + tarball参见 wiki (https://github.com/project-minigraf/minigraf/wiki/Use-Cases)

**一级(Tier 1)**绑定经过完整测试,并与每个核心版本同时发布。**二级(Tier 2)**绑定会构建并进行冒烟测试,按尽力而为的计划发布,属于实验性。当有真实用户需要时,绑定会升级为一级。一级支持的操作系统和文件系统为本地磁盘上的 Linux(ext4、xfs)、macOS(APFS)和 Windows(NTFS);NFSv4 支持但有注意事项,NFSv3 nolock 模式不支持多写者。详情参见支持层级。

面向 agent、移动端和浏览器的嵌入式图内存——SQLite 的简洁性 + Datomic 的时间模型。

语言绑定

语言包仓库
PythonPyPI 上的 minigraf (https://pypi.org/p/minigraf)minigraf-python (https://github.com/project-minigraf/minigraf-python)
Node.jsnpm 上的 minigraf (https://www.npmjs.com/package/minigraf)minigraf-node (https://github.com/project-minigraf/minigraf-node)
浏览器 WASMnpm 上的 @minigraf/browser (https://www.npmjs.com/package/@minigraf/browser)minigraf-wasm (https://github.com/project-minigraf/minigraf-wasm)
WASInpm 上的 @minigraf/wasi (https://www.npmjs.com/package/@minigraf/wasi)minigraf-wasm (https://github.com/project-minigraf/minigraf-wasm)
JavaMaven Central 上的 io.github.project-minigraf:minigraf-jvmminigraf-java (https://github.com/project-minigraf/minigraf-java)
AndroidMaven Central 上的 io.github.project-minigraf:minigraf-androidminigraf-android (https://github.com/project-minigraf/minigraf-android)
iOS/macOSSwift 绑定minigraf-swift (https://github.com/project-minigraf/minigraf-swift)
CC 绑定minigraf-c (https://github.com/project-minigraf/minigraf-c)

参见 Comparison (https://github.com/project-minigraf/minigraf/wiki/Comparison) wiki 页面,获取详细分析,包括时态数据库与时序数据库的对比。

面向 AI Agent

存储 agent 的信念,撤销和修正而不丢失历史,回放过去的状态来审计决策。每条事实同时携带事务时间(何时被记录)和有效时间(何时为真),因此你可以精确重建任何过去决策时刻的知识状态。

与向量存储搭配使用(GraphRAG 模式)效果尤佳:向量存储回答“什么是相似的?“;Minigraf 回答“关系是什么、是谁记录的、以及时间 T 时我们的信念是什么?”

在可视化工具中查看:agent 在做出推荐时相信的内容 (https://project-minigraf.github.io/minigraf-visualizer/#sample=agent-memory&tx=3&vt=any&e=:user-ana),以及随后的修正(按 → 前进一步)。

面向移动应用

离线优先的存储,支持追溯修正——双时态模型让你在更正输错的值时保留原始记录(在可视化工具中查看一个修正 (https://project-minigraf.github.io/minigraf-visualizer/#data=KHRyYW5zYWN0IHs6dmFsaWQtZnJvbSAiMjAyNS0wNi0wMSJ9CiAgICAgICAgICBbWzp1c2VyIDpoZWFsdGgvd2VpZ2h0LWtnIDgyLjVdXSkKKHJldHJhY3QgW1s6dXNlciA6aGVhbHRoL3dlaWdodC1rZyA4Mi41XV0pCih0cmFuc2FjdCB7OnZhbGlkLWZyb20gIjIwMjUtMDYtMDEifQogICAgICAgICAgW1s6dXNlciA6aGVhbHRoL3dlaWdodC1rZyA4MC41XV0p&title=Record+facts+offline%2C+correct+on+sync&vt=any&e=:user&view=map))。原生 Kotlin 和 Swift 绑定通过 UniFFI (https://github.com/mozilla/uniffi-rs) 以 Android .aar(Maven Central)和 iOS .xcframework(Swift Package Manager)形式发布。无需 Rust。

// Android (Kotlin)
val db = MiniGrafDb.open(context.filesDir.absolutePath + "/myapp.graph")
db.execute("""(transact [[:alice :person/name "Alice"] [:alice :person/age 30]])""")
val json = db.execute("(query [:find ?name :where [?e :person/name ?name]])")
// iOS (Swift)
let db = try MiniGrafDb.open(path: docsURL.appendingPathComponent("myapp.graph").path)
try db.execute(datalog: #"(transact [[:alice :person/name "Alice"] [:alice :person/age 30]])"#)
let json = try db.execute(datalog: "(query [:find ?name :where [?e :person/name ?name]])")

完整的设置和使用文档(Gradle 配置、SPM 集成、错误处理、线程)参见 Mobile Integration (https://github.com/project-minigraf/minigraf/wiki/Use-Cases#mobile-apps) wiki 章节。

面向 WASM / 浏览器

以 @minigraf/browser (https://www.npmjs.com/package/@minigraf/browser) 形式发布在 npm 上(基于 IndexedDB,wasm-pack)。WASI 构建(wasm32-wasip1)以 @minigraf/wasi (https://www.npmjs.com/package/@minigraf/wasi) 形式发布在 npm 上,并作为 GitHub Releases 产物提供(Wasmtime / Wasmer)。参见 Use Cases wiki (https://github.com/project-minigraf/minigraf/wiki/Use-Cases)。游乐场 (https://minigraf-playground.vercel.app/) 和时间旅行可视化工具 (https://project-minigraf.github.io/minigraf-visualizer/) 都是基于 @minigraf/browser 构建的。

面向 Python / Node.js / Java / C

语言绑定分别以 PyPI 上的 minigraf、npm 上的 minigraf(Node.js 原生插件)、Maven Central 上的 io.github.adityamukho:minigraf-jvm,以及 GitHub Releases 上的 C 头文件 + 预编译共享库形式发布。参见 Use Cases wiki (https://github.com/project-minigraf/minigraf/wiki/Use-Cases)。

定位范围

Minigraf 可以以以下形态运行:

  • ✅ 作为嵌入库
  • ✅ 作为独立二进制程序(交互式 REPL)
  • ✅ 浏览器 WASM —— @minigraf/browser(基于 IndexedDB,wasm-pack)
  • ✅ 服务端 WASM —— wasm32-wasip1 / WASI(Wasmtime、Wasmer、Cloudflare Workers)
  • ✅ Android、iOS、Python、Node.js、Java、C —— 通过 UniFFI / napi-rs / cbindgen

Minigraf 不会做成(这是设计决策):

  • 分布式 —— 无集群、无分片、无复制;每个 agent 实例拥有自己的 .graph 文件
  • 客户端-服务器 —— 核心中没有网络协议
  • 十亿级节点规模 —— 面向 <100 万节点优化(类似 SQLite)
  • 时序数据库 —— Minigraf 是一个时态数据库;参见 Comparison (https://github.com/project-minigraf/minigraf/wiki/Comparison#influxdb–prometheus–timescaledb-time-series-databases)

路线图

详见 ROADMAP.md,了解规划中的工作和当前方向。

性能

参见 BENCHMARKS.md,获取当前可复现的本地快照和基准测试命令。 | 100 万事实时的点查询 | 4.3–4.5 秒(有界模式的选择性 B+tree 查找;全属性扫描为 O(N)) | | 100 万事实时的打开耗时 | 1.31 秒(比 v5 快 2.4 倍——索引不再加载到内存) | | 100 万事实时的峰值堆内存 | 1.05 GB(比 v5 少约 21%——索引按需分页加载) |

文件型数据库对每条事实强制执行最大 4 080 序列化字节的大小限制。内存型数据库没有此限制。

持久性调优: 默认情况下每次写入都立即执行 fsync(SyncMode::Full)。批量加载/迁移场景中,如果失败后可以从检查点水位安全地重新运行,可以用 OpenOptions::new().synchronous(SyncMode::Normal) 换取吞吐量——在两种模式下 checkpoint() 仍然会无条件执行 fsync。完整的权衡分析和与之搭配的写入批处理模式参见 Performance Tuning wiki 页面 (https://github.com/project-minigraf/minigraf/wiki/Performance-Tuning#configuration-knobs)。

参与贡献

这是一个由个人维护、拥有长期愿景的项目。在提出功能建议前,请先阅读 PHILOSOPHY.md 和 ROADMAP.md。

开发环境搭建、代码规范和 PR 流程参见 CONTRIBUTING.md。

许可证

以下两种许可证任选其一:

  • Apache 许可证,2.0 版本(LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
  • MIT 许可证(LICENSE-MIT 或 http://opensource.org/licenses/MIT)

贡献

除非你明确说明,否则你有意提交以纳入本作品的任何贡献,均应按上述双重许可获得许可,不附带任何额外条款或条件。

相似文章

Show HN: HelixDB – 基于对象存储的图数据库

Hacker News Top

HelixDB 是一个用 Rust 构建的图-向量数据库,专为知识图谱和 AI 记忆设计,提供统一平台支持图、向量、键值、文档和关系型数据模型,并配有便于本地和云端部署的工具。