Coan-Teen, the female death spirit who walks without feet.
Cassandra CQL3 client for Clojure wrapping datastax/java-driver.
Please check the Changelog first if you are upgrading. Alia runs on Clojure >= 1.7 (we're using IReduceInit internally)
Add the following to your dependencies:
This would include all the codec extensions and extra libraries.
But the better thing to do is to pick and choose what you really need from alia's modules:
cc.qbits/alia Main module with all the basic alia functions (required).
cc.qbits/alia-async: core.async interface: query as streamed rows over channel, query as promise-chan
cc.qbits/alia-manifold: Manifold interface: query as streamed rows over manifold stream, query as deferred, etc
cc.qbits/alia-java-legacy-time: Codec for java legacy time types.
cc.qbits/alia-joda-time: Codec for joda-time types.
cc.qbits/alia-spec: clojure.spec for alia
cc.qbits/alia-component: Component integration for alia
If you wish to use Hayt you need to add it to your dependencies
Then require
/use
qbits.hayt
and you're good to go.
codox generated documentation.
Simple query execution using alia with hayt would look like this:
(execute session (select :users
(where {:name :foo})
(columns :bar "baz")))
But first things first: here is an example of a complete session using raw queries.
(require '[qbits.alia :as alia])
(def session (alia/session {:session-keyspace "alia"
:contact-points ["localhost:9042"]
:load-balancing-local-datacenter "Analytics"}))
Sessions are separate so that you can interact with multiple keyspaces from the same cluster definition.
(def session (alia/connect cluster))
(alia/execute session "CREATE KEYSPACE alia
WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3};")
(alia/execute session "CREATE TABLE users (user_name varchar,
first_name varchar,
last_name varchar,
auuid uuid,
birth_year bigint,
created timestamp,
valid boolean,
emails set<text>,
tags list<bigint>,
amap map<varchar, bigint>,
PRIMARY KEY (user_name));")
(alia/execute session "INSERT INTO users
(user_name, first_name, last_name, emails, birth_year, amap, tags, auuid,valid)
VALUES('frodo', 'Frodo', 'Baggins',
{'f@baggins.com', 'baggins@gmail.com'}, 1,
{'foo': 1, 'bar': 2}, [4, 5, 6],
1f84b56b-5481-4ee4-8236-8a3831ee5892, true);")
;; prepared statement with positional parameter(s)
(def prepared-statement (alia/prepare session "select * from users where user_name=?;"))
(alia/execute session prepared-statement {:values ["frodo"]})
>> ({:created nil,
:last_name "Baggins",
:emails #{"baggins@gmail.com" "f@baggins.com"},
:tags [4 5 6],
:first_name "Frodo",
:amap {"foo" 1, "bar" 2},
:auuid #uuid "1f84b56b-5481-4ee4-8236-8a3831ee5892",
:valid true,
:birth_year 1,
:user_name "frodo"})
;; prepared statement with named parameter(s)
(def prepared-statement (alia/prepare session "select * from users where user_name= :name limit :lmt;"))
(alia/execute session prepared-statement {:values {:name "frodo" :lmt (int 1)}})
There are currently 3 interfaces to use the asynchronous methods of
the underlying driver, the fundamental one being a simple
CompletableFuture
API, and then two alternative streaming APIs
built with core.async and manifold
CompletableFuture
@(execute-async session "select * from users;")
qbits.alia.async/execute-chan
has the same signature as the other execute
functions and returns a clojure/core.async
channel of rows, or an exception instance.
The channel supports backpressure, controlled by buffer-sizes and as rows are consumed from the channel more rows will be fetched to fill any buffers.
Once you run it you have a couple of options to pull data from it.
clojure.core.async/take!
which takes the channel as first argument
and a callback as second:(take! (execute-chan session "select * from users;")
(fn [rows-or-exception]
(do-something rows)))
clojure.core.async/<!!
to block and pull the rows/exception
from the channel.(def rows-or-exception (<!! (execute-chan session "select * from users;")))
clojure.core.async/merge
you can run a list of queries in
parallel and have the results fed to a single output chan:(let [merged (async/merge [(alia/execute-chan session (select :foo))
(alia/execute-chan session (select :bar))
(alia/execute-chan session (select :baz))])]
(go
(loop []
(when-let [result (<! merged)]
(println result)
(recur)))))
qbits.alia.async/execute
returns a promise-chan
with just the first
page of results
qbits.alia.async/execute-chan-pages
returns a channel of pages of results,
also supporting backpressure. The page objects are constructed by the
:result-set-fn
option.
qbits.alia.manifold/execute-stream
has the same signature as other execute
functions and resturns a manifold stream of rows, or an exception instance
As with core.async, the stream supports backpressure and as rows are take!
en
from the stream, more rows will be fetched according to available buffers.
qbits.alia.manifold/execute
returns a Deferred
with just the first page of
results
qbits.alia.manifold/execute-stream-pages
returns a stream of pages of
results, supporting backpressure. The page objects are constructed by the
:result-set-fn
option.
And it can do a lot more! Head to the codox generated documentation.
There is a nicer way to write your queries using Hayt, this should be familiar if you know Korma or ClojureQL. One of the major difference is that Hayt doesn't use macros and just generates maps, so if you need to compose clauses or queries together you can just use the clojure.core functions that work on maps.
Some examples:
(use 'qbits.hayt)
(select :foo (where {:bar 2}))
;; this generates a map
>> {:select :foo :where {:bar 2}}
(update :foo
(set-columns {:bar 1
:baz (inc-by 2)}
(where [[= :foo :bar]
[> :moo 3]
[> :meh 4]
[:in :baz [5 6 7]]]))
;; Composability using normal map manipulation functions
(def base (select :foo (where {:foo 1})))
(merge base
(columns :bar :baz)
(where {:bar 2})
(order-by [:bar :asc])
(using :ttl 10000))
;; To compile the queries just use ->raw
(->raw (select :foo))
> "SELECT * FROM foo;"
Alia supports hayt query direct execution, if you pass a non-compiled
query to execute
or execute-async
, it will be compiled and cached on a LU cache with a threshold of
100 (the cache function is user settable), so to be used carefully. The same is true with prepare
.
Ex
(execute session (select :users (where {:name :foo})))
It covers everything that is possible with CQL3 (functions, handling of collection types and their operations, ddl, prepared statements, etc). If you want to know more about it head to its codox documentation or Hayt's tests.
If you wish to support the work on this project you can do this here: patreon
Alia has a mailing list hosted on Google Groups. Do not hesitate to ask your questions there.
Copyright © 2013-2020 Max Penet, mccraigmccraig
Distributed under the Eclipse Public License, the same as Clojure.
Can you improve this documentation? These fine people already did:
Max Penet, Nicholas Corneau, Alex Karpov, mccraig mccraig of the clan mccraig, mccraigmccraig of the clan mccraig, Pierre-Yves Ritschard, Kirill Kondratenko, Andre R & LiamEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close