Skip to content

Instantly share code, notes, and snippets.

@daveray
Last active December 16, 2015 16:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daveray/5464943 to your computer and use it in GitHub Desktop.
Save daveray/5464943 to your computer and use it in GitHub Desktop.
astyanax clojure binding docs
; will open source in the near future. feedback/questions welcome.
(ns com.netflix.astyanax
"Clojure bindings for Cassandra via Astyanax
# Serializers
Serializer, when used in schemas (see below) are typically specified with a keyword.
The following are available, corresponding to the Astyanax serializers of the same
name:
:ascii, :big-integer, :boolean, :bytes, :char, :date, :double, :float, :integer
:long, :object, :short, :string, :time-uuid, and :uuid.
The serializer :* refers to Astyanax's TypeInferringSerializer.
There are a few additional serializers provided:
:keyword
The value is a string and is converted to/from a Clojure keyword.
:clojure
The value is a string which is written with clojure.core/prstr and read with
read-string. That is, you pass plain old Clojure objects and they are stored
in reader form as a string
:counter
A sentinel serializer used to mark counter columns
# Column Family Schema Definition
A column family schema is defined with a Clojure map, which must be normalized with the
normalize-schema function. Note that any number of schema can be defined for a single
column family if that's convenient. Also, since the schema is a map, it can easily be
manipulated, copied, introspected, etc. The map has the following keys:
:name
Keyword name of the column family
:rows
A map describing the rows in the column family. It can have the following keys:
:key-serializer Serializer (see above) used for row keys. Required.
:columns
A map describing the columns in the column family. It can have the following keys:
:name-serializer Serializer used for all column names. Responsible for turning bytes into
something usable and vice versa. If heterogenous names are used, see
:write-name-fn, and :read-name-fn below. Required.
:schemas Required. See below.
This map must also have a :schemas key which is a map from a unique, arbitrary, column type
id identifier (keyword) to a column description map. Each column description map describes
a particular column or \"type\" of column in a row. The map has the following keys:
:value-serializer Serializer used for the column value. Required.
:write-name-fn A function that takes some app-centric column name and converts it into
a raw column name ready to be serialized with :name-serializer. Optional.
Defaults to identity.
This is required because Astyanax doesn't provide a way of specifying
per-column name serializers
:read-name-fn A function that takes a deserialized column name and converts it into an
app-centric name. Opposite of :write-name-fn. Optional. Defaults to
identity.
This is required because Astyanax doesn't provide a way of specifying
per-column name serializers
:match-name-fn A function that takes a deserialized column name (result of :name-serializer)
and returns true if this column description corresponds to that name.
Optional, defaults to a function that matches the name to the id of the
column description.
This is used when a row has more than a fixed set of columns and there's a
need to map a retrieved column back to its type so that :read-name-fn, etc
can be applied.
A column descriptor may also just be the name of a serializer rather than a map, in which case
it's equivalent to specifying the :value-serializer. For example, this:
{:name-serializer :string
:schemas {:firstName {:value-serializer :string}
:lastName {:value-serializer :string}
:dob {:value-serializer :data}}}
could be written as just:
{:name-serializer :string
:schemas {:firstName :string
:lastName :string
:dob :date}}
In this case, it is assumed that the column names are serialized as strings \"firstName\"
\"lastName\" and \"dob\" in Cassandra.
# Column Maps
Throughout the API, Cassandra columns are represented as maps. This is the case whether
they're being written to a column family by client code or the result of a query. The
keys in a column map are as follows:
:type The type of the column in the schema definition,
i.e. [:columns :schemas <type>]
Always present.
:name The app-centric column name, as if it had been deserialized and run through
the column's :read-name-fn.
Always present.
:value The deserialized column value.
Present when put-ing a column in a column family, or when the column is the
result of a query.
:ttl The ttl in seconds, or nil if none has been assigned to the column
Present when put-ing a column in a column family, or when the column is the
result of a query.
:timestamp The column timestamp as a long. If the column is a counter, this will be *nil*.
Present when the column is the result of a query.
# Query and Mutation Plans
All Cassandra operations are represented by plans, i.e. Clojure maps which describe what to
execute. This namespace (com.netflix.astyanax) provides a number of functions for constructing
these plan maps and executing them. Typically, you can do this in a nice, declarative style.
# Query Plans
Assuming #'user holds a column family schema as described above, here are some simple
query examples:
; read all columns from one row
(-> user
select
(row 123456)
(execute my-keyspace))
; read a slice of columns from one row
(-> user
select
(row 123456)
(column :firstName)
(column :lastName)
(execute my-keyspace))
; read a slice of columns from a couple rows
(-> user
select
(row 123456)
(row 98765)
(column :firstName)
(column :lastName)
(execute my-keyspace))
# Mutation Plans
The form of mutation plans (put and delete) is basically the same as query plans:
; Set the values of some columns in a row
(-> user
delete
(row 123456)
(column :firstName \"Jim\")
(column :lastName \"Jones\")
(execute my-keyspace))
; Delete a whole row
(-> user
delete
(row 123456)
(execute my-keyspace))
; Delete a slice of columns from one row
(-> user
delete
(row 123456)
(column :firstName)
(column :lastName)
(execute my-keyspace))
See #'com.netflix.astyanax/column for many more details. There's also support for column
ranges, limit, reverse, etc.
"
...)
@mpenet
Copy link

mpenet commented Apr 26, 2013

Looks good! I was hoping for somebody to do that eventually :)

I did something similar with schemas on https://github.com/mpenet/casyn , maybe it can give you a few ideas
ex about composites support, using nippy instead of the reader for clj serialisation or default column value types with possible exceptions depending on column name ("columns for this row have string name, and long value, but if name is "foo" then value is an int").

If you plan to integrate with CQL at some point (since thrift partially supports cql3), also have a look at https://github.com/mpenet/hayt

@zcaudate
Copy link

zcaudate commented Jan 8, 2014

when will this library be open-sourced? I'm really hoping to get my hands on it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment