# simple-triplestore   [![Latest Docs]][docs.rs] [![Latest Crate]][crates.io] [Latest Docs]: https://img.shields.io/docsrs/simple-triplestore/0.0.2?label=docs [Latest Crate]: https://img.shields.io/crates/v/simple-triplestore [docs.rs]: https://docs.rs/simple-triplestore/latest/ [crates.io]: https://crates.io/crates/simple-triplestore A [triplestore](https://en.wikipedia.org/wiki/Triplestore) implementation which can be used as a flexible graph database with support for custom node and edge properties. ## Data Model Each vertex and edge (collectively called `nodes`) are associated with an id (i.e. `u64` or [Ulid](https://docs.rs/ulid/latest/ulid/struct.Ulid.html)). 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: * Subject, Predicate, Object * Predicate, Object, Subject * Object, Subject, Predicate 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. ## Supported Key-Value Backends * [Memory](https://docs.rs/simple-triplestore/latest/simple_triplestore/struct.MemTripleStore.html) * [Sled](https://docs.rs/simple-triplestore/latest/simple_triplestore/struct.SledTripleStore.html) ( with the `sled` feature ) ## Example Pull in various includes we need: ```rust 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. ```rust 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. ```rust assert_eq!( db.run(query!{ ? -?-> [node_3] })? .iter_edges(EdgeOrder::default()) .map(|r| r.expect("ok")) .collect::>(), [ (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: ```rust assert_eq!( db.run(query!{ ? -[edge]-> ? })? .iter_edges(EdgeOrder::default()) .map(|r| r.expect("ok")) .collect::>(), [ (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])), ] ); ```