Skip to content

syncrypt/ex_orient

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ExOrient

An OrientDB query builder providing a nicer syntax to Orient SQL and uses MarcoPolo to execute commands.

Installation

  1. Add ex_orient to your list of dependencies in mix.exs: elixir def deps do [{:ex_orient, "~> 1.0.0"}] end

  2. Ensure ex_orient is started before your application: elixir def application do [applications: [:ex_orient]] end

Configuration

In your config.exs file, add the following:

config :ex_orient,
  pool_size: 5,
  pool_max_overflow: 10,
  user: "admin",
  password: "admin",
  connection: {:db, "GratefulDeadConcerts", :document},
  host: "localhost",
  port: 2424

Adjust the values to fit your needs.

Usage

The naming is as similar as possibly to the SQL commands, and every command takes a keyword list of commands. The functions return a 2-tuple of a query string and a map of params (the map is passed off to MarcoPolo, which does the job of interpolating them into the string). To execute a command, simply pipe it to DB.exec/1 or DB.command/1. This library was written this way to accomodate subqueries.

Here's a simple example:

command = ExOrient.DB.insert(into: ProgrammingLanguage, set: [name: "Elixir"])
# {"INSERT INTO ProgrammingLanguage SET name = :set_name", %{"set_name" => "Elixir"}}

DB.exec(command)

And an example of building up a larger query using subqueries:

alias ExOrient.DB

DB.create(
  edge: "works_for",
  from: DB.select(from: Employee, where: %{name: "Paul"}),
  to: DB.select(from: Company, where: %{name: "Remesh"})
) |> DB.exec()

A relatively comprehensive example performing lots of operations:

iex(1)> alias ExOrient.DB
iex(2)> alias MarcoPolo.Document

iex(3)> DB.create(class: Employee, extends: "V") |> DB.exec()
{:ok, 26}

iex(4)> DB.create(class: Company, extends: "V") |> DB.exec()
{:ok, 27}

iex(5)> DB.create(class: "works_for", extends: "E") |> DB.exec()
{:ok, 28}

iex(6)> DB.create(class: "owns", extends: "E") |> DB.exec()
{:ok, 29}

iex(7)> DB.insert(into: Employee, set: [name: "Elon"]) |> DB.exec()
{:ok,
 %MarcoPolo.Document{class: "Employee", fields: %{"name" => "Elon"},
  rid: #MarcoPolo.RID<#22:0>, version: 1}}

iex(8)> DB.insert(into: Employee, content: %{name: "John Doe"}) |> DB.exec()
{:ok,
 %MarcoPolo.Document{class: "Employee", fields: %{"name" => "John Doe"},
  rid: #MarcoPolo.RID<#22:1>, version: 1}}

iex(9)> DB.insert(into: Employee, content: %{name: "Jane Doe"}) |> DB.exec()
{:ok,
 %MarcoPolo.Document{class: "Employee", fields: %{"name" => "Jane Doe"},
  rid: #MarcoPolo.RID<#22:2>, version: 1}}

iex(10)> DB.insert(into: Company, set: [name: "Tesla"]) |> DB.exec()
{:ok,
 %MarcoPolo.Document{class: "Company", fields: %{"name" => "Tesla"},
  rid: #MarcoPolo.RID<#23:0>, version: 1}}

iex(11)> DB.insert(into: Company, set: [name: "SpaceX"]) |> DB.exec()
{:ok,
 %MarcoPolo.Document{class: "Company", fields: %{"name" => "SpaceX"},
  rid: #MarcoPolo.RID<#23:1>, version: 1}}

iex(12)> employees = DB.select(from: Employee, where: [name: "John Doe", name: "Jane Doe", name: "Elon"], logical: :or)
{"SELECT FROM Employee WHERE name = :where_name_444 OR name = :where_name_445 OR name = :where_name_446",
 %{"where_name_444" => "John Doe", "where_name_445" => "Jane Doe",
   "where_name_446" => "Elon"}}

iex(13)> elon = "#22:0"
"#22:0"

iex(14)> companies = DB.select(from: Company, where: [name: "Tesla", name: "SpaceX"], logical: :or)
{"SELECT FROM Company WHERE name = :where_name_723 OR name = :where_name_724",
 %{"where_name_723" => "Tesla", "where_name_724" => "SpaceX"}}

iex(16)> DB.create(edge: "owns", from: elon, to: companies) |> DB.exec()
{:ok,
 [%MarcoPolo.Document{class: "owns",
   fields: %{"in" => #MarcoPolo.RID<#23:0>, "out" => #MarcoPolo.RID<#22:0>},
   rid: #MarcoPolo.RID<#26:0>, version: 1},
  %MarcoPolo.Document{class: "owns",
   fields: %{"in" => #MarcoPolo.RID<#23:1>, "out" => #MarcoPolo.RID<#22:0>},
   rid: #MarcoPolo.RID<#26:1>, version: 2}]}

iex(18)> DB.create(edge: "works_for", from: employees, to: "#23:1") |> DB.exec()
{:ok,
 [%MarcoPolo.Document{class: "works_for",
   fields: %{"in" => #MarcoPolo.RID<#23:1>, "out" => #MarcoPolo.RID<#22:2>},
   rid: #MarcoPolo.RID<#24:5>, version: 1},
  %MarcoPolo.Document{class: "works_for",
   fields: %{"in" => #MarcoPolo.RID<#23:1>, "out" => #MarcoPolo.RID<#22:0>},
   rid: #MarcoPolo.RID<#24:6>, version: 2},
  %MarcoPolo.Document{class: "works_for",
   fields: %{"in" => #MarcoPolo.RID<#23:1>, "out" => #MarcoPolo.RID<#22:1>},
   rid: #MarcoPolo.RID<#24:7>, version: 2}]}

iex(21)> DB.select(["expand(in('works_for'))"], from: Company, where: %{"name.toLowerCase()": "spacex"}) |> DB.exec()
{:ok,
 [%MarcoPolo.Document{class: "Employee",
   fields: %{"name" => "Jane Doe",
     "out_works_for" => {:link_bag, [#MarcoPolo.RID<#24:5>]}},
   rid: #MarcoPolo.RID<#22:2>, version: 2},
  %MarcoPolo.Document{class: "Employee",
   fields: %{"name" => "Elon",
     "out_owns" => {:link_bag, [#MarcoPolo.RID<#26:0>, #MarcoPolo.RID<#26:1>]},
     "out_works_for" => {:link_bag, [#MarcoPolo.RID<#24:6>]}},
   rid: #MarcoPolo.RID<#22:0>, version: 3},
  %MarcoPolo.Document{class: "Employee",
   fields: %{"name" => "John Doe",
     "out_works_for" => {:link_bag, [#MarcoPolo.RID<#24:7>]}},
   rid: #MarcoPolo.RID<#22:1>, version: 2}]}

Contributing

Run tests (this requires a connection to a local database, check the config file):

mix test

Run tests excluding the ones that require a database connection:

mix test --exclude db

Make a Pull Request.

About

OrientDB query builder for Elixir

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published