triton alternatives and similar packages
Based on the "ORM and Datamapping" category.
Alternatively, view triton alternatives based on common mentions on social networks and blogs.
-
paper_trail
Track and record all the changes in your database with Ecto. Revert back to anytime in history. -
ExAudit
Ecto auditing library that transparently tracks changes and can revert them. -
ecto_psql_extras
Ecto PostgreSQL database performance insights. Locks, index usage, buffer cache hit ratios, vacuum stats and more. -
arbor
Ecto elixir adjacency list and tree traversal. Supports Ecto versions 2 and 3. -
sqlitex
An Elixir wrapper around esqlite. Allows access to sqlite3 databases. -
boltun
Transforms notifications from the Postgres LISTEN/NOTIFY mechanism into callback execution -
sql_dust
Easy. Simple. Powerful. Generate (complex) SQL queries using magical Elixir SQL dust. -
walex
Listen to Postgres change events and do stuff with the data directly in Elixir
Collect and Analyze Billions of Data Points in Real Time
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of triton or a related project?
Popular Comparisons
README
Triton
Pure Elixir Cassandra ORM built on top of Xandra.
Add Triton to your deps
Add triton to your deps.
def deps() do
[{:triton, "~> 0.2"}]
end
Configure Triton
Single Cluster
config :triton,
clusters: [
[
conn: Triton.Conn,
nodes: ["127.0.0.1"],
pool: Xandra.Cluster,
underlying_pool: DBConnection.Poolboy,
pool_size: 10,
keyspace: "my_keyspace",
health_check_delay: 2500, # optional: (default is 5000)
health_check_interval: 500 # optional: (default is 1000)
]
]
Multi-Cluster
config :triton,
clusters: [
[
conn: Cluster1.Conn,
nodes: ["127.0.0.1"],
pool: Xandra.Cluster,
underlying_pool: DBConnection.Poolboy,
pool_size: 10,
keyspace: "cluster_1_keyspace",
health_check_delay: 2500, # optional: (default is 5000)
health_check_interval: 500 # optional: (default is 1000)
],
[
conn: Cluster2.Conn,
nodes: ["127.0.0.1"],
pool: Xandra.Cluster,
underlying_pool: DBConnection.Poolboy,
pool_size: 10,
keyspace: "cluster_2_keyspace",
health_check_delay: 2500, # optional: (default is 5000)
health_check_interval: 500 # optional: (default is 1000)
]
]
Health Check
If DB gets disconnected, resulting in a DBConnection error, Triton will attempt to reconnect.
You can specify the health_check_delay and health_check_interval via the config for each cluster.
Defining a Keyspace
First, define your keyspace. Triton will create the keyspace for your after compile if it does not exist.
defmodule Schema.Keyspace do
use Triton.Keyspace
keyspace :my_keyspace, conn: Triton.Conn do
with_options [
replication: "{'class' : 'SimpleStrategy', 'replication_factor': 3}"
]
end
end
Defining a Table
You can define as many tables as you want. Triton will create tables for you if they do not exist.
If you would like Triton to auto-create tables for you after compile, you must require your Keyspace module.
defmodule Schema.User do
require Schema.Keyspace
use Triton.Table
table :users, keyspace: Schema.Keyspace do
field :user_id, :bigint, validators: [presence: true] # validators using vex
field :username, :text
field :display_name, :text
field :password, :text
field :email, :text
field :phone, :text
field :notifications, {:map, "<text, text>"}
field :friends, {:set, "<text>"}
field :posts, {:list, "<text>"}
field :updated, :timestamp
field :created, :timestamp, transform: &Schema.Helper.DateHelper.to_ms/1 # transform field data
partition_key [:user_id]
end
end
Defining a Materialized View
An example of a materialized view users_by_email with fields user_id, email, display_name, password.
Also demonstrates adding options like gc_grace_seconds and clustering_order_by.
defmodule Schema.UserByEmail do
require Schema.User # if you want to auto-create after compile
use Triton.MaterializedView
materialized_view :users_by_email, from: Schema.User do
fields [
:user_id,
:email,
:display_name,
:password
]
partition_key [:email]
cluster_columns [:user_id]
with_options [
gc_grace_seconds: 172_800,
clustering_order_by: [
email: :asc,
user_id: :desc
]
]
end
end
An example of materialized view users_by_email with all fields
defmodule Schema.UserByEmail do
require Schema.User
use Triton.MaterializedView
materialized_view :users_by_email, from: Schema.User do
fields :all
partition_key [:email]
cluster_columns [:user_id]
end
end
Querying
First, import Triton.Query
alias Schema.User
import Triton.Query
Select a single user where user_id = using a prepared statement.
User
|> prepared(user_id: id)
|> select([:user_id, :username])
|> where(user_id: :user_id)
|> User.one
Select users with IDs of 1, 2, or 3
User
|> select([:user_id, :username])
|> where(user_id: [in: [1, 2, 3]])
|> limit(10)
|> allow_filtering # you can allow filtering on any query
|> User.all
Select user with email [email protected]
UserByEmail
|> select([:display_name])
|> where(email: "[email protected]")
|> User.one
Comparison / Range Queries
Select messages created before timestamp
MessagesByDate
|> select([:message_id, :text])
|> where(channel_id: 1, created: ["<=": timestamp])
|> limit(20)
|> MessagesByDate.all
Select messages created between timestamp_a and timestamp_b
MessagesByDate
|> select([:message_id, :text])
|> where(channel_id: 1, created: [">=": timestamp_a], created: [<: timestamp_b])
|> MessagesByDate.all
Streaming
Stream all messages
MessagesByDate
|> select(:all)
|> where(channel_id: 1)
|> MessagesByDate.stream(page_size: 20)
Which returns {:ok, stream} or {:error, msg}
Inserting, Updating, & Deleting
Again, lets import Triton.Query for the necessary macros.
alias Schema.User
import Triton.Query
Add a user (if it doesn't already exist) with username username using a prepared statement that substitutes user_id into :user_id
User
|> prepared(user_id: user_id, username: username)
|> insert(user_id: :user_id, username: :username)
|> if_not_exists
|> User.save
Update a user's username, and make sure to check that their previous username was what we expected.
User
|> update(username: username)
|> where(user_id: user_id)
|> constrain(username: previous_username)
|> User.save
Lets delete a user given a user_id
User
|> prepared(user_id: user_id)
|> delete(:all) # here :all refers to all fields
|> where(user_id: :user_id)
|> User.del
Lets delete that same user, with consistency: :quorum
User
|> prepared(user_id: user_id)
|> delete(:all) # here :all refers to all fields
|> where(user_id: :user_id)
|> User.del(consistency: :quorum)
Batch update 4 users in 1 Cassandra request.
[
User |> update(username: "username1") |> where(user_id: 1),
User |> update(username: "username2") |> where(user_id: 2),
User |> update(username: "username3") |> where(user_id: 3),
User |> update(username: "username4") |> where(user_id: 4)
] |> User.batch_execute
Working with Collections
Update the notifications map to {'mentions': '3', 'replies': '3'}. Overwrites the entire map.
User
|> update(notifications: "{'mentions': '5', 'replies': '3'}")
|> where(user_id: 10)
|> User.save
Update notification mentions to '5'.
User
|> update("notifications['mentions']": "5")
|> where(user_id: 10)
|> User.save
Update the friends set
User
|> update(friends: "{'jill', 'bob', 'emma'}")
|> where(user_id: 10)
|> User.save
Add a friend_id to friends set
User
|> update(friends: "friends + {'oscar'}")
|> where(user_id: 10)
|> User.save
Remove friend from set
User
|> update(friends: "friends - {'oscar'}")
|> where(user_id: 10)
|> User.save
Update the posts list
User
|> update(posts: "['post1', 'post2', 'post3']")
|> where(user_id: 10)
|> User.save
Append to posts list
User
|> update(posts: "posts + ['post4']")
|> where(user_id: 10)
|> User.save
Prepend to posts list
User
|> update(posts: "['post0'] + posts")
|> where(user_id: 10)
|> User.save
Pre-populating data
You can pre-populate data with Triton at compile time with Triton.Setup
defmodule PrepopulateModule do
use Triton.Setup
import Triton.Query
require Schema.User
alias Schema.User
# create an admin user if it doesn't exist
setup do
User
|> insert(
user_id: @admin_user_id,
username: @admin_user_username,
display_name: @admin_user_display_name,
password: Bcrypt.hashpwsalt(@admin_user_password),
email: @admin_user_email,
created: @admin_user_created
) |> if_not_exists
end
end
Automatic Schema Creation
Triton attempts to create your keyspace, tables, and materialized views after compile if they do not exist.
This means that your build server will need access to your production DB if you want to automatically create your schema in prod. The alternative is simply to create your production schemas yourself.
Consistency levels
For dev, you may want to consider running ccm with more than 1 node if you are doing queries at anything more than consistency: :one.