Packages

NebulaGraph client for Elixir — connection pooling, session management, and rich result decoding.

Current section

Files

Jump to
nebula_graph_ex lib nebula_graph_ex.ex
Raw

lib/nebula_graph_ex.ex

defmodule NebulaGraphEx do
@moduledoc """
Elixir client for [NebulaGraph](https://www.nebula-graph.io/) — a distributed
open-source graph database.
`nebula_graph_ex` provides:
* **Connection pooling** via `DBConnection` (the same library used by
Postgrex and MyXQL).
* **Full type decoding** — NebulaGraph's `Value` union is converted to
idiomatic Elixir terms: integers, floats, binaries, booleans, `nil`,
`%Vertex{}`, `%Edge{}`, `%Path{}`, date/time structs, geography, and more.
* **Parameterised queries** — values are encoded as Thrift `Value` structs,
never interpolated into statement strings.
* **TLS / SSL** support out of the box.
* **Telemetry** events for every query start, stop, and exception.
## Quick start
### 1. Add to `mix.exs`
defp deps do
[
{:nebula_graph_ex, "~> 0.1"}
]
end
### 2. Define a graph module
Borrowing from Ecto's Repo pattern, create a module for your graph connection:
# lib/my_app/graph.ex
defmodule MyApp.Graph do
use NebulaGraphEx.Graph, otp_app: :my_app
end
### 3. Configure it
# config/config.exs
config :my_app, MyApp.Graph,
hostname: "localhost",
port: 9669,
space: "my_graph",
pool_size: 10
# config/runtime.exs — secrets resolved at boot, not compile time
config :my_app, MyApp.Graph,
hostname: System.fetch_env!("NEBULA_HOST"),
password: fn -> System.fetch_env!("NEBULA_PASS") end
### 4. Add to your supervision tree
def start(_type, _args) do
children = [MyApp.Graph]
Supervisor.start_link(children, strategy: :one_for_one)
end
### 5. Run queries
alias NebulaGraphEx.{Record, ResultSet}
# Simple query
{:ok, rs} = MyApp.Graph.query("MATCH (v:Player) RETURN v.name, v.age LIMIT 5")
rs |> ResultSet.count()
#=> 5
rs |> ResultSet.rows() |> Enum.map(&Record.to_map/1)
#=> [%{"v.name" => "Tim Duncan", "v.age" => 42}, ...]
# Parameterised query (always use params for user input)
{:ok, rs} =
MyApp.Graph.query(
"MATCH (v:Player{name: $name}) RETURN v.age AS age",
%{"name" => "Tim Duncan"}
)
rs |> ResultSet.first!() |> Record.get!("age")
#=> 42
# Bang variant raises NebulaGraphEx.Error on failure
MyApp.Graph.query!("RETURN 1+1 AS n")
|> ResultSet.first!()
|> Record.get!("n")
#=> 2
### 6. Check connection status
{:ok, status} = MyApp.Graph.status()
status.connected?
#=> true
status.queryable?
#=> true
{:error, failed_status} = MyApp.Graph.status(probe_statement: "THIS IS NOT VALID NGQL")
failed_status.error_details
#=> %{code: :e_syntax_error, message: "...", category: :query, statement: "THIS IS NOT VALID NGQL"}
## Working with graph types
When a column contains a vertex, edge, or path, it is decoded automatically:
{:ok, rs} = MyApp.Graph.query("MATCH (v:Player) RETURN v LIMIT 1")
rs
|> ResultSet.first!()
|> Record.get!("v")
#=> %NebulaGraphEx.Types.Vertex{
# vid: "player100",
# tags: [%NebulaGraphEx.Types.Tag{name: "Player", props: %{"name" => "Tim Duncan"}}]
# }
rs
|> ResultSet.first!()
|> Record.get!("v")
|> NebulaGraphEx.Types.Vertex.prop("Player", "name")
#=> "Tim Duncan"
## Per-query options
Options can be overridden at call-site:
MyApp.Graph.query(stmt, %{},
space: "other_space",
timeout: 60_000,
decode_mapper: &Record.to_map/1
)
## Configuration reference
All options accepted by `NebulaGraphEx.Graph.start_link/1` are documented in
`NebulaGraphEx.Options`.
## Telemetry
Attach the default logger handler in development:
NebulaGraphEx.Telemetry.attach_default_handler()
Or attach your own handler for production metrics — see `NebulaGraphEx.Telemetry`
for event names, measurements, and metadata shapes.
## Updating the Thrift IDL
NebulaGraph's wire protocol is defined by the Thrift IDL files in
`priv/thrift/`. To upgrade to a newer NebulaGraph server version:
1. Replace the files in `priv/thrift/` with the upstream versions from
[vesoft-inc/nebula](https://github.com/vesoft-inc/nebula/tree/master/src/interface).
2. Re-add the `namespace elixir` lines (the only lines that differ from upstream).
3. Run `mix compile`.
"""
end