Elixir Humane Graph DB
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
config
lib
test
.gitignore
LICENSE
README.md
mix.exs
mix.lock

README.md

Thoth

Thoth is a simple GDB meant for local usage that can withstand a high number of vertices.

Installation

If available in Hex, the package can be installed as:

  1. Add thoth to your list of dependencies in mix.exs:

    def deps do [{:thoth, "~> 0.0.5"}] end

  2. Ensure thoth is started before your application:

    def application do [applications: [:thoth]] end

Usage

Creating the Models

defmodule Person do
    defstruct name: nil, age: nil, type: :person
end

# A Model struct has to implement Thoth.Model's id/1 that creates a uniquq id per instance
defimpl Thoth.Model, for: Person do
    def id (%Person{name: name}) do
        name |> String.downcase |> String.replace(" ", "_") |> String.to_atom
    end
end

defmodule Place do
    defstruct type: :place, name: nil
end

defimpl Thoth.Model, for: Place do
    def id (%Place{name: name}) do
        String.to_atom String.downcase name
    end
end

# It can also derive it for the default "UUIDv4" implementation
defmodule Post do
    @derive Thoth.Model
    defstruct type: :post, text: nil, is_comment: false
end

Creating the Graph

defmodule FB.Scenario do
    require Person
    require Place
    require Post
    require Thoth.Persistence
    require Thoth.Entities

    def run path do
        # Create new graph
        dag = Thoth.Persistence.load
        il = Thoth.Entities.add!(dag, %Place{name: "Israel"})
        fr = Thoth.Entities.add!(dag, %Place{name: "France"})
        au = Thoth.Entities.add!(dag, %Place{name: "Australia"})
        ca = Thoth.Entities.add!(dag, %Place{name: "Canada"})
        sp = Thoth.Entities.add!(dag, %Place{name: "Spain"})

        jaubourg = Thoth.Entities.add!(dag, %Person{name: "Julian Auborg", age: 20})

        # connecting 2 entities:
        # connect!(graph, source, target, connection_type) -- create a single directed conncetion
        # connect!(graph, source, target, connection_type, true) -- create a mutual directed conncetion of the same type
        # connect!(graph, source, target, connection_type, reverse_connection_type) -- create a two directed connections,
        # one from source to target, the other from target to source
        Thoth.Entities.connect!(dag, jaubourg, il, :from, :natives)
        Thoth.Entities.connect!(dag, jaubourg, ca, :lives_in, :dwellers)

        phiggins = Thoth.Entities.add!(dag, %Person{name: "Peter Higgins", age: 21})
        Thoth.Entities.connect!(dag, phiggins, il, :from, :natives)
        Thoth.Entities.connect!(dag, phiggins, ca, :lives_in, :dwellers)

        blowery = Thoth.Entities.add!(dag, %Person{name: "Ben Lowery", age: 21})
        Thoth.Entities.connect!(dag, blowery, ca, :from, :natives)
        Thoth.Entities.connect!(dag, blowery, fr, :lives_in, :dwellers)

        jeresig = Thoth.Entities.add!(dag, %Person{name: "John Resig", age: 22})
        Thoth.Entities.connect!(dag, jeresig, ca, :from, :natives)
        Thoth.Entities.connect!(dag, jeresig, fr, :lives_in, :dwellers)

        slightlylate = Thoth.Entities.add!(dag, %Person{name: "Alex Russell", age: 20})
        Thoth.Entities.connect!(dag, slightlylate, au, :from, :natives)
        Thoth.Entities.connect!(dag, slightlylate, sp, :lives_in, :dwellers)

        ajpiano = Thoth.Entities.add!(dag, %Person{name: "Adam Sontag", age: 24})
        Thoth.Entities.connect!(dag, ajpiano, au, :from, :natives)
        Thoth.Entities.connect!(dag, ajpiano, sp, :lives_in, :dwellers)

        Thoth.Entities.connect!(dag, ajpiano, phiggins, :friends, true)        
        Thoth.Entities.connect!(dag, jaubourg, phiggins, :friends, true)        
        Thoth.Entities.connect!(dag, ajpiano, slightlylate, :friends, true)        
        Thoth.Entities.connect!(dag, jeresig, slightlylate, :friends, true)        
        Thoth.Entities.connect!(dag, ajpiano, jaubourg, :friends, true)        
        Thoth.Entities.connect!(dag, ajpiano, blowery, :friends, true)        

        post = Thoth.Entities.add!(dag, %Post{text: "Hell of a day!"})
        Thoth.Entities.connect!(dag, ajpiano, post, :posted, :author)
        Thoth.Entities.connect!(dag, phiggins, post, :likes, :likers)
        Thoth.Entities.connect!(dag, blowery, post, :likes, :likers)
        
        comment = Thoth.Entities.add!(dag, %Post{text: "Awesome!", is_comment: true})
        Thoth.Entities.connect!(dag, phiggins, comment, :posted, :author)
        Thoth.Entities.connect!(dag, post, comment, :comments)
        Thoth.Entities.connect!(dag, ajpiano, comment, :likes, :likers)

        comment = Thoth.Entities.add!(dag, %Post{text: "Fuck you, mate", is_comment: true})
        Thoth.Entities.connect!(dag, slightlylate, comment, :posted, :author)
        Thoth.Entities.connect!(dag, post, comment, :comments)
        subcomment = Thoth.Entities.add!(dag, %Post{text: "Huh?", is_comment: true})
        Thoth.Entities.connect!(dag, phiggins, subcomment, :posted, :author)
        Thoth.Entities.connect!(dag, comment, subcomment, :comments)

        # Save graph to path
        Thoth.Persistence.save(dag, path)
    end
end

Using the Graph

dag = Thoth.Persistence.load('./test') # load the graph
friends_of_friends = Thoth.Query.query(
  dag, 
  :alex_russell,
  [:friends, :friends]
)
assert length(friends_of_friends) === 4