Last active
December 16, 2015 16:40
-
-
Save daveray/5464943 to your computer and use it in GitHub Desktop.
astyanax clojure binding docs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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. | |
" | |
...) |
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
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