6 个版本
0.2.0 | 2022 年 2 月 17 日 |
---|---|
0.2.0-pre.4 | 2021 年 12 月 29 日 |
0.1.1 | 2020 年 9 月 9 日 |
#5 in #modifying
155KB
3.5K SLoC
owoof
这是一个受 Datomic 启发的查询构建器,使用类似 datalog 的格式来查询和修改 SQLite 数据库周围的信息。
这是一个个人项目,可能不适用于任何严肃的应用。
这是一个作为 Rust 库实现的。它有文档说明,您可以阅读源代码或可能找到在 docs.rs 上发布的 文档。
有两个 Rust 可执行目标。一个提供命令行界面(如下所示),另一个可用于从 CSV 文件导入数据。
CLI
使用 cargo build
编译此软件,使用 --features cli --bin cli
。
CLI 可用于初始化新的数据库文件、断言/创建、撤回/删除或查询信息。
以下是一些示例
$ echo '[{":db/attribute": ":pet/name"},
{":pet/name": "Garfield"},
{":pet/name": "Odie"},
{":pet/name": "Spot"},
{":db/attribute": ":person/name"},
{":db/attribute": ":person/starship"},
{":person/name": "Jon Arbuckle"},
{":person/name": "Lieutenant Commander Data",
":person/starship": "USS Enterprise (NCC-1701-D)"}]' \
| owoof assert
[
"#45e9d8e9-51ea-47e6-8172-fc8179f8fbb7",
"#4aa95e29-8d45-470b-98a7-ee39aae1b9c9",
"#2450b9e6-71a4-4311-b93e-3920eebb2c06",
"#c544251c-a279-4809-b9b6-7d3cd68d2f2c",
"#19a4cba1-6fc7-4904-ad36-e8502445412f",
"#f1bf032d-b036-4633-b6f1-78664e44603c",
"#e7ecd66e-222f-44bc-9932-c778aa26d6ea",
"#af32cfdb-b0f1-4bbc-830f-1eb83e4380a3"
]
$ echo '[{":db/attribute": ":pet/owner"},
{":db/id": "#4aa95e29-8d45-470b-98a7-ee39aae1b9c9",
":pet/owner": "#e7ecd66e-222f-44bc-9932-c778aa26d6ea"},
{":db/id": "#2450b9e6-71a4-4311-b93e-3920eebb2c06",
":pet/owner": "#e7ecd66e-222f-44bc-9932-c778aa26d6ea"},
{":db/id": "#c544251c-a279-4809-b9b6-7d3cd68d2f2c",
":pet/owner": "#af32cfdb-b0f1-4bbc-830f-1eb83e4380a3"}]' \
| owoof assert
[
"#ffc46ae2-1bde-4c08-bfea-09db8241aa2b",
"#4aa95e29-8d45-470b-98a7-ee39aae1b9c9",
"#2450b9e6-71a4-4311-b93e-3920eebb2c06",
"#c544251c-a279-4809-b9b6-7d3cd68d2f2c"
]
$ owoof '?pet :pet/owner ?owner' \
--show '?pet :pet/name' \
--show '?owner :person/name'
[
[
{ ":pet/name": "Garfield" },
{ ":person/name": "Jon Arbuckle" }
],
[
{ ":pet/name": "Odie" },
{ ":person/name": "Jon Arbuckle" }
],
[
{ ":pet/name": "Spot" },
{ ":person/name": "Lieutenant Commander Data" }
]
]
$ owoof '?person :person/starship "USS Enterprise (NCC-1701-D)"' \
'?pet :pet/owner ?person' \
'?pet :pet/name ?n'
[
"Spot"
]
# Or, suppose you know someone's name and their pet's name but don't know the attribute
# that relates them... (But also this doesn't use indexes well so don't do it.)
$ owoof '?person :person/name "Lieutenant Commander Data"' \
'?pet ?owner ?person' \
'?pet :pet/name "Spot"' \
--show '?owner :db/attribute'
[
{ ":db/attribute": ":pet/owner" }
]
数据集来自 goodbooks-10k。
$ owoof '?r :rating/score 1' \
'?r :rating/book ?b' \
'?b :book/authors "Dan Brown"' \
--show '?r :rating/user' \
--show '?b :book/title' \
--limit 5
[
[
{ ":rating/user": 9 },
{ ":book/title": "Angels & Demons (Robert Langdon, #1)" }
],
[
{ ":rating/user": 58 },
{ ":book/title": "The Da Vinci Code (Robert Langdon, #2)" }
],
[
{ ":rating/user": 65 },
{ ":book/title": "The Da Vinci Code (Robert Langdon, #2)" }
],
[
{ ":rating/user": 80 },
{ ":book/title": "The Da Vinci Code (Robert Langdon, #2)" }
],
[
{ ":rating/user": 89 },
{ ":book/title": "The Da Vinci Code (Robert Langdon, #2)" }
]
]
导入 goodbooks-10k
-
初始化一个空数据库。
$ owoof init
-
导入书籍并输出数据的副本,每个导入的行都有一个
:db/id
列。$ owoof-csv --output -- \ :book/title \ :book/authors \ :book/isbn \ :book/avg-rating\ average_rating \ < goodbooks-10k/books.csv \ > /tmp/imported-books
-
导入评分,我们使用
mlr
将评分与导入的书籍关联起来。$ mlr --csv join \ -f /tmp/imported-books \ -j book_id \ < goodbooks-10k/ratings.csv \ | owoof-csv -- \ ':rating/book :db/id' \ ':rating/score rating' \ ':rating/user user_id'
-
这需要一些时间(可能是几分钟),然后您可以执行类似以下操作。
$ owoof '?calvin :book/title "The Complete Calvin and Hobbes"' \ '?rating :rating/book ?calvin' \ '?rating :rating/score 1' \ '?rating :rating/user ?u' \ '?more-great-takes :rating/user ?u' \ '?more-great-takes :rating/book ?b' \ '?more-great-takes :rating/score 5' \ --show '?b :book/title :book/avg-rating' \ --asc '?b :book/avg-rating'
它应该会输出一些答案。
待办事项/注意事项
-
目前测试不全面。
应该强制执行架构,因此不要删除正在使用的属性,但我还没有完成验证这项工作,所以可能会有一些惊喜。
-
性能并不特别可靠。
版本 0.2 在特定属性上添加了部分索引,这大大提高了搜索性能。然而,没有对值进行索引。某些查询受此影响更大,因此性能并不可靠。
目前值索引的难点在于 SQLite 的查询计划器在不应选择它的情况下会优先选择它。这不是一个好的索引,而应该是最后的手段--它也非常庞大。
-
功能还不丰富,约束确保了等价性,尚不支持涉及范围或逻辑运算的约束,而且我还没有测试它在 0.2 中进行的架构更改后的表现如何。
内部待办事项
-
从连接创建 DontWoof。
-
选择借用网络有点奇怪。我尝试将其分开,但仍然很奇怪。不确定该怎么办。一个考虑是,将选择查询推送到查询中只是从网络中借用。也许可以放宽这个限制?
-
测试引用计数?添加清理代码,移除零rc的soup并运行pragma optimize。
-
也许可以添加一些更新机制,简化撤回和断言?
-
由于该属性的实体和值对于该属性的元组是相同的,所以
:db/id
属性有点愚蠢。对于对象形式/映射来说很有用;例如
{":db/id": ...}
。但也许有更巧妙的方式来按某种方式分组?(比如与每个数据库存储的形式关联的某种主键……🤔)
参见
与该软件版本0.1关联的博客文章:https://froghat.ca/blag/dont-woof
许可证
本软件受Apache许可证,版本2.0许可。
依赖项
~23MB
~447K SLoC