Crates.io | simple-triplestore |
lib.rs | simple-triplestore |
version | 0.2.0-alpha.1 |
source | src |
created_at | 2024-07-26 16:34:11.985157 |
updated_at | 2024-08-01 17:59:04.135618 |
description | A simple graph database for storing triples with support for custom node and edge properties. |
homepage | |
repository | https://github.com/rcythr/simple-triplestore |
max_upload_size | |
id | 1316407 |
size | 272,836 |
A triplestore implementation which can be used as a flexible graph database with support for custom node and edge properties.
Each vertex and edge (collectively called nodes
) are associated with an id (i.e. u64
or Ulid).
Property data is stored as
Id -> NodeProps
Id -> EdgeProps
.Graph relationships are stored three times as (Id, Id, Id) -> Id
with the following sort orders:
This allows for any graph query to be decomposed into a range query on the lookup with the ideal ordering. For example,
query!{ a -b-> ? }
becomes a query on the subject-predicate-object table.query!{ ? -a-> b }
becomes a query on the position-object-subject table.query!{ a -?-> b }
becomes a query on the object-subject-position table.Pull in various includes we need:
use ulid::Ulid;
use simple_triplestore::prelude::*;
let mut db = MemTripleStore::new(UlidIdGenerator::new());
Get some identifiers. In real applications these will come from an index or another lookup table.
let node_1 = Ulid(123);
let node_2 = Ulid(456);
let node_3 = Ulid(789);
let edge = Ulid(999);
Insert nodes and edges with user-defined property types. For a given TripleStore we can have one type for Nodes and one for Edges.
db.insert_node(node_1, "foo".to_string())?;
db.insert_node(node_2, "bar".to_string())?;
db.insert_node(node_3, "baz".to_string())?;
db.insert_edge(Triple{sub: node_1, pred: edge, obj: node_2}, Vec::from([1,2,3]))?;
db.insert_edge(Triple{sub: node_1, pred: edge, obj: node_3}, Vec::from([4,5,6]))?;
We can now query for edges which end at node_3
, and find that there is only one.
assert_eq!(
db.run(query!{ ? -?-> [node_3] })?
.iter_edges(EdgeOrder::default())
.map(|r| r.expect("ok"))
.collect::<Vec<_>>(),
[
(Triple{sub: node_1, pred: edge, obj: node_3}, Vec::from([4,5,6])),
]
);
We can also query for all edges which have the predicate edge
, and find both of the edges we added:
assert_eq!(
db.run(query!{ ? -[edge]-> ? })?
.iter_edges(EdgeOrder::default())
.map(|r| r.expect("ok"))
.collect::<Vec<_>>(),
[
(Triple{sub: node_1, pred: edge, obj: node_2}, Vec::from([1,2,3])),
(Triple{sub: node_1, pred: edge, obj: node_3}, Vec::from([4,5,6])),
]
);