Would anyone else like to see a driver for TypeDB?

Hello everyone,

I don’t know if my post is appropriate. If it isn’t, you can delete it.

After a year of designing and defining the requirements of a web application (interactive dictionary of the languages ​​Hebrew, Aramaic, Latin, Greek, Sanskrit, English, German, Spanish and French, I have found that their interconnections and similarities in phonetic sounds and the numerical values ​​of the letters connects them with each other) Elixir/Phoenix is ​​chosen to accompany us on this journey. Finding the right database was much more difficult, but I still found something that met my criteria.

This database is called TypeDB, but unfortunately it currently does not have a driver for Erlang.

Therefore, on the one hand, I would like to draw attention to this database, and on the other hand, I would like to ask the members of this group, if you like this database, to convince the TypeDB team to create a driver for Erlang.

The easiest way to do this is on github, e.g. B. through comments and likes under the following link:

https://github.com/typedb/typedb-driver/issues/586

First of all, I hope for your understanding of my contribution and am grateful for your support.

3 Likes

I took a quick look at TypeDB but couldn’t get what are the very clear advantages compared to e.g. PostgreSQL?

3 Likes

Hello,

TypeDB offers significant advantages over PostgreSQL, especially in scenarios that require complex knowledge representation, semantic modeling, and automated reasoning. Here are the key benefits of TypeDB:

Rich Schema Capabilities

  • Complex Entities and Relationships: TypeDB supports a rich schema model that allows for the representation of complex entities, attributes, and relationships, ideal for applications with intricate data interrelations.
  • Type Hierarchies: Supports type hierarchies and inheritance, simplifying the modeling and querying of hierarchical structures.
  • Reasoning Engine: The built-in reasoning engine can infer new data based on existing data and rules, enabling automated data augmentation and consistency checks.

Advanced Querying with TypeQL

  • Declarative Query Language: TypeQL, TypeDB’s query language, is designed for expressing complex queries and patterns effortlessly. It excels at handling multi-hop queries and graph traversals.
  • Pattern Matching: Graql’s expressive pattern matching simplifies querying complex relationships and constraints.

Graph-Based Storage

  • Efficient Relationship Handling: TypeDB’s underlying graph-based storage is optimized for managing complex relationships and interconnected data efficiently.
  • Optimized for Relationships: Excels in scenarios where relationships and their traversals are central, such as knowledge graphs and network analyses.

Automated Inference and Consistency

  • Automated Inference: The reasoning engine can automatically infer new facts and relationships from defined rules, providing powerful knowledge discovery and data enrichment.
  • Consistency Checks: Enforces data consistency and integrity through logical constraints and rules.

Ideal Use Cases

  • Knowledge Graphs: Perfect for building and querying complex knowledge graphs where relationships are essential.
  • Biological Data: Suitable for bioinformatics and domains requiring detailed modeling of complex systems.
  • AI and Machine Learning: Beneficial for AI applications needing rich, interconnected data representations.

I hope that I have highlighted the main advantages of TypeDB.

A good article to consider TypeDB versus SQL databases can be found here:

Best regards
Sergiusz

4 Likes

For me that would be an argument to not use it :joy: .

I’m also positive that you will not be able to integrate it with Ecto, the de-facto tool we use for database interactions in our apps, and building another “ORM” from scratch would be a huge time investment.

2 Likes

Thank you for your comment.

I have tought, that this would be possible with bi-directional communication over WebSockets?
Maybe with Phoenix Channels?

SurrealDB works on a SDK in this way.

TypeDB provides a Rust driver. Binding a Rust NIF via Rustler is probably a better approach. This will not require the TypeDB devs to maintain one more driver indefinitely (big ask), and there are probably people here that have that skill.

3 Likes

While it might be a bit tedious they do provide gRPC definitions typedb-protocol/proto at development · typedb/typedb-protocol · GitHub . It could be safer and easier to use compared to writing a port/NIF manually.

2 Likes

Hi. TypeDB engineer here!

Is this still something you’d be interested in seeing @Sergiusz ? Unfortunately my experience in Elixir and Erlang is zero, but as @jkwchui noted, the fastest way to build a new DB driver is by piggybacking on the Rust driver.

I’d imagine that, if you wanted an Erlang driver for TypeDB, one engineer with AI assistance could whip up something functional within days :slight_smile:

As an experiment, I asked AI to sketch the project keeping it high-level; this is what it came up with - I have no idea how accurate it is.

typedb_ex/
├── mix.exs
├── native/
│   └── typedb_ex_nif/
│       ├── Cargo.toml
│       └── src/lib.rs
└── lib/
    └── typedb_ex.ex
defp deps do
  [
    {:rustler, "~> 0.30"}
  ]
end

def project do
  [
    compilers: [:rustler] ++ Mix.compilers(),
    rustler_crates: rustler_crates()
  ]
end

defp rustler_crates do
  [
    typedb_ex_nif: [
      path: "native/typedb_ex_nif",
      mode: :release
    ]
  ]
end
[package]
name = "typedb_ex_nif"
version = "0.1.0"
edition = "2021"

[lib]
name = "typedb_ex_nif"
crate-type = ["cdylib"]

[dependencies]
rustler = "0.30"
typedb-driver = "2.28"  # Official TypeDB Rust driver
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
use rustler::{Env, Term, NifResult, ResourceArc};
use typedb_driver::{DatabaseManager, Session, Transaction, TypeDBDriver, Driver, SessionType, TransactionType};
use std::sync::Mutex;

rustler::init!("Elixir.TypeDBEx.Nif", [connect, query]);

struct DriverResource {
    driver: Mutex<TypeDBDriver>,
}

#[rustler::nif]
fn connect<'a>(env: Env<'a>, address: String) -> NifResult<Term<'a>> {
    let driver = TypeDBDriver::new(address).map_err(|e| rustler::Error::Atom("connection_failed"))?;
    let resource = ResourceArc::new(DriverResource { driver: Mutex::new(driver) });
    Ok(resource.to_term(env))
}

#[rustler::nif(schedule = "DirtyCpu")]
fn query<'a>(
    env: Env<'a>,
    driver_res: ResourceArc<DriverResource>,
    database: String,
    query_str: String,
) -> NifResult<Term<'a>> {
    let driver = driver_res.driver.lock().unwrap();

    let databases = DatabaseManager::new(&driver);
    let session = Session::new(&databases, &database, SessionType::Data)
        .map_err(|_| rustler::Error::Atom("session_failed"))?;

    let mut tx = session
        .transaction(TransactionType::Read)
        .map_err(|_| rustler::Error::Atom("tx_failed"))?;

    let answers = tx
        .query(&query_str)
        .map_err(|_| rustler::Error::Atom("query_failed"))?;

    let mut results = vec![];
    for answer in answers {
        results.push(format!("{:?}", answer)); // Simplified
    }

    Ok(results.to_term(env))
}
defmodule TypeDBEx do
  use Rustler, otp_app: :typedb_ex, crate: "typedb_ex_nif"

  def connect(_address), do: :erlang.nif_error(:nif_not_loaded)
  def query(_driver, _db, _query), do: :erlang.nif_error(:nif_not_loaded)

  # High-level wrapper
  def with_connection(address, fun) do
    {:ok, driver} = connect(address)
    try do
      fun.(driver)
    after
      # Close driver (add close/1 NIF if needed)
    end
  end

  def run_query(driver, db, query) do
    query(driver, db, query)
  end
end
{:ok, driver} = TypeDBEx.connect("localhost:1729")

result = TypeDBEx.run_query(driver, "my_db", "match $x isa person, has name $n; get $n;")

IO.inspect(result)
# => ["name: \"Alice\"", "name: \"Bob\""]
4 Likes