14 releases (breaking)

0.13.0 Aug 19, 2024
0.11.1 Aug 13, 2024
0.7.0 Jul 30, 2024

#633 in Database interfaces

Download history 64/week @ 2024-06-27 322/week @ 2024-07-04 150/week @ 2024-07-11 30/week @ 2024-07-18 342/week @ 2024-07-25 218/week @ 2024-08-01 360/week @ 2024-08-08 287/week @ 2024-08-15 21/week @ 2024-08-22

938 downloads per month

MIT license

56KB
963 lines

test crates docs cov cov

GruPHst

An in-memory graph database


GruPHst

Possible to persists on file (just because is something that we always expect from an in-memory databases).

Early state of development with lot of TODOs, just doing nerdy things with Graph Databases while trying to learn some Rust.

Documentation

Code Coverage

Basic Usage

use gruphst::{edge::Edge, graphs::Graphs, vertex::Vertex};
use std::error::Error;

// The idea it's to create some graph related with 
// the Middle-Earth, relating some characters and
// places

fn main() -> Result<(), Box<dyn Error>> {
    // Create a new vertex
    let frodo = Vertex::new("Frodo");
       
    // Let's create another vertex
    let mut gandalf = Vertex::new("Gandalf");
     
    // A vertex can have attributes
    gandalf.set_attr("known as", "The Gray");
    gandalf.set_attr("years old", 24000);

    // Now lets make a relation between these two friends
    // by creating an Edge
    let mut edge = Edge::create(&gandalf, "friend of", &frodo);

    // An Edge can have attributes
    edge.set_attr("duration in years", 42);

    // Now we need something to hold, and store the created Edge
    // and the new ones that we'll create later.
    // Lets init a Graphs, we could do this step at the begining 
    // of the main function.
    let mut graphs = Graphs::init("middle-earth");
    
    // Now we add the edge or relation between Gandalf and Frodo
    graphs.add_edge(&edge, None);

    // We can add another relation or Edge to the graphs
    // for these two friends, e.g.
    graphs.add_edge(&Edge::create(&frodo, "has best friend", &gandalf), None);

    // Lets create more vertices for places and characters and edges
    // for the relation between them
    let mut sam = Vertex::new("Samwise");
    sam.set_attr("surname", "Gamgee");
    graphs.add_edge(
        &Edge::create(
            &sam,
            "has best friend",
            &frodo),
        None);

    let mut vertex = Vertex::new("The Shire");

    // Vertices and Edges has a uuid generated on creation
    let id_vertex_the_shire = vertex.get_id();

    graphs.add_edge(&Edge::create(&frodo, "lives at", &vertex), None); 

    vertex = Vertex::new("Isengard");
    vertex.set_attr("type", "tower");

    graphs.add_edge(&Edge::create(&Vertex::new("Saruman"), "lives at", &vertex), None); 

    // we can use the id or the label to retrieve a Vertex that we have on Graph
    let the_shire = graphs.find_vertex_by_id(id_vertex_the_shire.as_str(), None)?;

    graphs.add_edge(&Edge::create(&sam, "lives at", &the_shire), None); 

    // Now we can do things like get stats of the Graphs
    let stats = graphs.get_stats();

    // and print it
    println!("{:#?}", stats);
    // GraphsStats {
    //    mem: 1578,
    //    total_edges: 6,
    //    total_graphs: 1,
    //    total_attr: 8,
    //    total_vertices: 12,
    //    uniq_rel: 3,
    //    max_mem: 104857600,
    // }
    
    // or get some value from stats
    // like the amount of vertices
    assert_eq!(stats.get_total_vertices(), 12);

    // We can print the current Graphs object
    println!("{:#?}", graphs);

    // We can retrieve the uniq relations from the graph
    let unique_relations_vertices = graphs.uniq_relations();
    assert_eq!(unique_relations_vertices, vec!["friend of", "has best friend", "lives at"]);

    // Also possible to retrieve the vertices that has a certain
    // relation in
    let vertices_with_relation_in = graphs.has_relation_in("lives at", None)?; 
    assert_eq!(vertices_with_relation_in[0].get_label(), "The Shire");
    assert_eq!(vertices_with_relation_in[1].get_label(), "Isengard");

    // Or get the edge that has a vertex with an attribute equals to
    let found = graphs.attr_equals_to("years old", 24000, None)?;
    assert_eq!(found[0].get_from_vertex().get_label(), "Gandalf");

    // Since we have a humble middle-earth network
    // we can persists it for another day
    // a file called "middle-earth.grphst" will be created, 
    // later we can load it with:
    // let loaded_graphs = Graphs::load("middle-earth.grphst")?;
    graphs.persists()?;

    Ok(())
}

Install

Run the following Cargo command in your project directory:

$ cargo add gruphst

Or add the following line to your Cargo.toml:

gruphst = "0.13.0"

Tests & Coverage & Benchmarking

To run tests locally This will show output, if a test name is provided as argument will run this tests

$ ./scripts/local-test.sh

If nodemon is installed, you can use the tests in watch mode:

$ ./scripts/dev-watch.sh

Coverage

$ ./scripts/test-coverage.sh

It will generate a report called tarpauling-report.html

Benchmarking

$ ./scripts/benchmarking.sh

Right now only covers add_edge method.

Examples

Check the Rock Paper Scissors Spock Lizard example.

Check the Middle-Earth example.

Also worth to check the tests folder.


Thanks @ChrisMcMStone for all the help and memory tips ;-)

Feedback from usage and contributions are very welcome. Also if you like it, please leave a ⭐ I would appreciate it ;)

Dependencies

~1–11MB
~80K SLoC