The ClojureWerkz Blog

News and updates about ClojureWerkz projects

Cassaforte 1.3.0 Is Released

TL;DR

Cassaforte is a new Clojure client for Apache Cassandra. It is built around CQL 3 and focuses on ease of use. You will likely find that using Cassandra from Clojure has never been so easy.

1.3.0 is a minor release that introduces a few minor features and improves compatibility with Cassandra 2.0.

Changes between Cassaforte 1.2.x and 1.3.0

Clojure 1.6 By Default

The project now depends on org.clojure/clojure version 1.6.0. It is still compatible with Clojure 1.4 and if your project.clj depends on a different version, it will be used, but 1.6 is the default now.

We encourage all users to upgrade to 1.6, it is a drop-in replacement for the majority of projects out there.

Cassandra Java Driver Update

Cassandra Java driver has been updated to 2.0.x.

UUID Generation Helpers

clojurewerkz.cassaforte.uuids is a new namespace that provides UUID generation helpers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(require '[clojurewerkz.cassaforte.uuids :as uuids])

(uuids/random)
;= #uuid "d43fdc16-a9c3-4d0f-8809-512115289537"

(uuids/time-based)
;= #uuid "90cf6f40-4584-11e3-90c2-65c7571b1a52"

(uuids/unix-timestamp (uuids/time-based))
;= 1383592179743

(u/start-of (u/unix-timestamp (u/time-based)))
;= #uuid "ad1fd130-4584-11e3-8080-808080808080"

(u/end-of (u/unix-timestamp (u/time-based)))
;= #uuid "b31abb3f-4584-11e3-7f7f-7f7f7f7f7f7f"

Hayt Update

Hayt dependency has been updated to 1.4.1, which supports if-not-exists in create-keyspace:

1
2
3
4
5
(create-keyspace "main"
           (if-not-exists)
           (with {:replication
                    {:class "SimpleStrategy"
                     :replication_factor 1 }}))

Extra Clauses Support in insert-batch

It is now possible to use extra CQL clauses for every statement in a batch insert (e.g. to specify TTL):

1
2
3
(cql/insert-batch "table"
  {:something "cats"}
  [{:something "dogs"} (using :ttl 60)])

Contributed by Sam Neubardt.

Alternative where syntax

Now it is possible to specify hash in where clause, which makes queries more composable:

1
2
3
4
(select :users
        (where {:city "Munich"
                :age [> (int 5)]})
        (allow-filtering true))

Batch Insert Improvements

Clauses to be specified for each record in insert-batch:

1
2
3
(let [input [[{:name "Alex" :city "Munich"} (using :ttl 350)]
             [{:name "Alex" :city "Munich"} (using :ttl 350)]]]
  (insert-batch th/session :users input))

Contributed by Sam Neubardt.

News and Updates

New releases and updates are announced on Twitter. Cassaforte also has a mailing list, feel free to ask questions and report issues there.

Cassaforte is a ClojureWerkz Project

Cassaforte is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Monger, a Clojure MongoDB client for a more civilized age
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • EEP, a Clojure library for stream (event) processing
  • Neocons, a Clojure client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Cassaforte, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

Michael on behalf of the ClojureWerkz Team.

Monger 2.0.0-rc1 Is Released

TL;DR

Monger is an idiomatic Clojure MongoDB driver for a more civilized age. It has batteries included, offers powerful expressive query DSL, strives to support every MongoDB 2.0+ feature and has sane defaults. It also has solid documentation.

2.0.0 is a major backwards-incompatible release that implements in Monger the major breaking API changes announced earlier for several ClojureWerkz projects.

Changes between 1.8.0 and 2.0.0

2.0 is a major release that has breaking public API changes.

Explicit Connection/DB/GridFS Argument

In Monger 2.0, all key public API functions require an explicit DB/connection/GridFS object to be provided instead of relying on a shared dynamic var. This makes Monger much easier to use with systems such as Component and Jig, as well as concurrent applications that need to work with multiple connections, database, or GridFS filesystems.

In other words, instead of

1
2
3
(require '[monger.collection :as mc])

(mc/insert "libraries" {:name "Monger"})

it is now necessary to do

1
2
3
(require '[monger.collection :as mc])

(mc/insert db "libraries" {:name "Monger"})

This also means that monger.core/connect! and monger.core/connect-via-uri! were removed, as was monger.multi namespaces.

To connect to MongoDB, use monger.core/connect:

1
2
3
(require '[monger.core :as mg])

(let [conn (mg/connect)])

or monger.core/connect-via-uri:

1
2
3
(require '[monger.core :as mg])

(let [{:keys [conn db]} (mg/connect-via-uri "mongodb://clojurewerkz/monger:monger@127.0.0.1/monger-test4")])

To get a database reference, use monger.core/get-db, which now requires a connection object:

1
2
3
4
(require '[monger.core :as mg])

(let [conn (mg/connect)
      db   (mg/get-db conn "monger-test")])

Options as Maps

Functions that take options now require a proper Clojure map instead of pseudo keyword arguments:

1
2
3
4
5
# in Monger 1.x
(mc/update db coll {} {:score 0} :multi true)

# in Monger 2.x
(mc/update db coll {} {:score 0} {:multi true})

Change Log

Monger change log is available on GitHub.

Monger is a ClojureWerkz Project

Monger is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Cassaforte, a Clojure Cassandra client built around CQL
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Welle, a Riak client with batteries included
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Monger, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

@michaelklishin on behalf of the ClojureWerkz Team

Langohr 2.10.1 Is Released

TL;DR

Langohr is a small Clojure RabbitMQ client.

2.10.1 is a bug fix release.

Changes between Langohr 2.9.x and 2.10.1

Retries for all IOExceptions During Recovery

All IOException subclasses thrown during connection recovery attempts will now be retried.

Contributed by Paul Bellamy (Xively).

RabbitMQ Java Client Upgrade

RabbitMQ Java client dependency has been updated to 3.3.1.

Change Log

Langohr change log is available on GitHub.

Langohr is a ClojureWerkz Project

Langohr is part of the group of libraries known as ClojureWerkz, together with

  • Elastisch, a minimalistic well documented Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL 3.0
  • Monger, a Clojure MongoDB client for a more civilized age
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Langohr, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About The Author

Michael on behalf of the ClojureWerkz Team

Monger 1.8.0 Is Released

TL;DR

Monger is an idiomatic Clojure MongoDB driver for a more civilized age. It has batteries included, offers powerful expressive query DSL, strives to support every MongoDB 2.0+ feature and has sane defaults. It also has solid documentation.

1.8.0 is a minor backwards-compatible release that updates MongoDB Java driver and adds a few minor features. The next release will be 2.0 with some major breaking API changes that we’ve announced earlier.

Changes between 1.7.0 and 1.8.0

Clojure 1.6

Monger now depends on org.clojure/clojure version 1.6.0. It is still compatible with Clojure 1.4 and if your project.clj depends on a different version, it will be used, but 1.6 is the default now.

monger.result Use with WriteConcerns is Deprecated

MongoDB Java driver 2.12.x no longer guarantees connection affinity for thread pool threads.

This means that WriteConcern#getLastError is no longer a safe from concurrency hazards. Therefore the use of monger.result functions on WriteConcern instances is now deprecated in MongoDB Java client and Monger.

MongoDB Java Driver Update

MongoDB Java driver dependency has been updated to 2.12.x.

Default WriteConcern Change

Monger now uses WriteConcern/ACKNOWLEDGED by default. Functionality-wise it is the same as WriteConcern/SAFE in earlier versions.

monger.core/connect-via-uri

monger.core/connect-via-uri is a version of monger.core/connect-via-uri! which returns the connection instead of mutating a var.

It should be used by projects that are built from reloadable components, together with monger.multi.*.

Future Plans

The next Monger release will be 2.0 with some major breaking API changes that we’ve announced earlier.

Change Log

Monger change log is available on GitHub.

Monger is a ClojureWerkz Project

Monger is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Cassaforte, a Clojure Cassandra client built around CQL
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Welle, a Riak client with batteries included
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Monger, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

@michaelklishin on behalf of the ClojureWerkz Team

Meltdown 1.0.0 Is Released

TL;DR

Meltdown is a Clojure interface to Reactor, an asynchronous programming, event passing and stream processing toolkit for the JVM.

1.0.0 is based on Reactor 1.1.0 which is now final.

Changes between 1.0.0-beta12 and 1.0.0

Reactor Update

Reactor is updated to 1.1.0.RELEASE.

Change log

Meltodwn change log is available on GitHub.

Meltdown is a ClojureWerkz Project

Meltdown is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Meltdown, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

Michael on behalf of the ClojureWerkz Team

Welle 2.0.0 Is Released

TL;DR

Welle is an expressive Clojure client for Riak with batteries included.

2.0.0 is a major release that has breaking API changes and introduces an important bug fix, dependency updates and support for Riak 1.4 features.

It does not include our recently announced “explicit client” changes. Those will be part of 3.0.

Changes between Welle 1.5.0 and 2.0

Welle 2.0 has breaking API changes in clojurewerkz.welle.kv functions.

Changes in K/V Function Return Values

This is a breaking API change.

Welle 2.0 changes how Riak responses are represented as Clojure maps. Welle now will correctly preserve all vector clocks associated with multiple siblings in the response and the response itself.

This means that welle.kv/modify will work correctly and won’t make sibling explosions worse.

The most important part of the change is how responses are represented: every response is an immutable map that has :result key as well as other metadata keys (:has-value?, :has-siblings?, :modified?, :content-type and so on).

This contrasts with earlier versions, where results were returned directly by functions such as welle.kv/fetch, it is now possible to destructure the response in order to obtain the returned value:

1
2
3
4
(require '[clojurewerkz.welle.kv :as kv])

(let [{:keys [result] :as m} (kv/fetch bucket-name k :r 1)]
  (comment "Do something with the result"))

Here are the keys that clojurewerkz.welle.kv/fetch returns now for every response:

  • :result: one or more objects returned by Riak
  • :vclock: vector clock of the response
  • :has-siblings?: true if response has siblings
  • :has-value?: true if response is non-empty
  • :modified?: false when conditional GET returned a non-modified response
  • :deleted?: true if this object has been deleted but there is a vclock for it

Clojure 1.3 Support Dropped

Welle no longer supports Clojure 1.3.

Counters Support (Riak 1.4+)

clojurewerkz.welle.counters is a new namespace that provides operations on Riak counters:

1
2
3
4
5
6
7
8
9
10
11
12
(require '[clojurewerkz.welle.counters :as wcnt])

(let [bucket-name "counters"
      counter     "hit-points"]
  (wcnt/increment-counter bucket-name counter)
  ;= 1
  (wcnt/fetch-counter bucket-name counter)
  ;= 1
  (wcnt/increment-counter bucket-name counter :value 2))
  ;= 3
  (wcnt/increment-counter bucket-name counter :value -3))
  ;= 0

Riak Java Client Update

Welle now uses Riak Java client 1.4.2.

Cheshire Update

Cheshire has been updated to 5.2.0.

clj-http Update

clj-http has been updated to 0.7.7.

Support Update

ClojureWerkz Support has been updated to 0.20.0.

Ports Support in PB Cluster Client

While creating a protocol buffer cluster client you can now provide hosts and ports separated by a colon, e.g. “127.0.0.1:10017”. If a port is not provided, the default port will be used.

So now you can use following format:

1
2
3
4
5
6
7
(wc/connect-to-cluster-via-pb! ["10.0.1.2",
                  "10.0.1.3",
              "10.0.1.4",
              "10.0.1.5",
              "10.0.1.6"])

as well as following format:

clojure (wc/connect-to-cluster-via-pb! [“127.0.0.1:10017”,

                "127.0.0.1:10027",
            "127.0.0.1:10037",
            "127.0.0.1:10047"])

“`

Validateur Dependency Dropped

Validateur is no longer a dependency of Welle.

Don’t worry, they still work well together.

Optional Keywordization of Keys With JSON Serialization

Automatic JSON serialization previously unconditionally converted keys to keywords. This may be a problem for some projects, because keywords are not garbage collected.

clojurewerkz.welle.conversion/*convert-json-keys-to-keywords* is a new dynamic var that controls this behavior. When bound to false, automatic JSON serialization won’t convert keys to keywords.

Change Log

Welle change log is available on GitHub.

Welle is a ClojureWerkz Project

Welle is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB client for a more civilized age
  • Neocons, a feature rich idiomatic Clojure client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Welle, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

Donations

ClojureWerkz accepts donations. If you feel like our projects save you time, consider donating. Thanks.

Michael on behalf of the ClojureWerkz Team

Balagan 1.0.0 Is Released

What is Balagan

Balagan is a tiny Clojure library for data structure transformation inspired by Enlive.

Supported Clojure Versions

Balagan targets Clojure 1.4+, tested against 3 Clojure versions x 2 JDKs on travis-ci.org, and is released under the Eclipse Public License.

Documentation and Examples

Balagan builds on ideas from Enlive. It may help to get familiar with them first.

Let’s say you’re working on a Data Access layer for the application. You have a user entry represented as hash:

1
2
3
4
(def user
  {:name "Alex"
   :birth-year 1990
   :nickname "ifesdjeen"})

Transformation

Now, we can start transforming users the way we want: add, remove fields based on certain conditions.

1
2
3
4
5
(update user
           []                  (add-field :cool-dude true) ;; adds a field :cool-dude with value true
           (new-path [:age])   #(- 2014 (:birth-year %))   ;; explicit adding of a new field, calculated from the existing data
           (new-path [:posts]) #(fetch-posts (:name %))    ;; fetching some related data from the DB
           [:posts :*]         #(update-posts %))       ;; apply some transformations to all the fetched posts, if there are any

Queries

Queries are very similar to how you’d query your data with filter in Clojure:

1
2
3
4
(let [data {:a {:b [{:c 1} {:c 2} {:c 3}]
                :d [{:c 5} {:c 6} {:c 7}]}}]
  (select data  [:* :* even? :c]))
;; => (1 3 5 7)  

Results are returned in the order they’ve been seen in your data structure, however you should be aware of the fact that iterating over the hash in Clojure doesn’t guarantee you order.

Path Queries

Path queries are most useful when you’d like to fire a function against some part of your data (be it processing, database initialization or anything else.

You can also run predicate queries based on your map, for example if you want to configure your database servers from rather big and complex config:

1
2
3
4
5
6
7
8
9
(def conf {:db
           {:redis {:cache  [{:host "host01" :port 1234} {:host "host02" :port 1234}]
                    :pubsub [{:host "host01" :port 1234} {:host "host02" :port 1234}]}}
           :cassandra [{:host "host01"} {:host "host02"}]})

(with-paths conf
        [:db :redis :cache]  configure-redis-cache
        [:db :redis :pubsub] configure-redis-pubsub
        [:db :cassandra]     configure-cassandra)

In this example, configure-redis-cache funciton will receive two arguments: value and path:

1
2
3
4
5
6
7
(defn configure-redis-cache
  [value path]
  (println "Value: " value)
  (println "Path: " path))

;; => Value: [{:host host01, :port 1234} {:host host02, :port 1234}]
;; => Path: [:db :redis :cache]

You can also do wildcard-matching with :*, for example:

1
2
3
4
5
(b/select {:a {:b {:c 1} :d {:c 2}}}
          [:a :* :c] (fn [val path]
                       (if (= path [:a :b :c])
                         (is (= val 1))
                         (is (= val 2)))))

Learn more in the documentation section.

Community

To subscribe for announcements of releases, important changes and so on, please follow @ClojureWerkz on Twitter.

License

Distributed under the Eclipse Public License, the same as Clojure.

The source is available on GitHub. We also use GitHub to track issues.

About the Author

The ClojureWerkz Team.

Meltdown 1.0.0-beta12 Is Released

TL;DR

Meltdown is a Clojure interface to Reactor, an asynchronous programming, event passing and stream processing toolkit for the JVM.

1.0.0-beta12 is a development milestone with minor improvements, and likely the last pre-release version before 1.0.

Changes between 1.0.0-beta11 and 1.0.0-beta12

Reactor Update

Reactor is updated to 1.1.0.RC1.

Changes between 1.0.0-beta10 and 1.0.0-beta11

Set Membereship Selector

clojurewerkz.meltdown.selectors/set-membership is a new selector that matches on element membership in a set:

1
2
3
4
5
(require '[clojurewerkz.meltdown.reactor   :as mr])
(require '[clojurewerkz.meltdown.selectors :as ms)

(let [r   (mr/create)]
  (mr/on r (ms/set-membership #{"white" "red" "blue"} (fn [evt])))

Change log

Meltodwn change log is available on GitHub.

Meltdown is a ClojureWerkz Project

Meltdown is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Elastisch, a Clojure client for ElasticSearch
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Quartzite, a powerful scheduling library

and several others. If you like Meltdown, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

Michael on behalf of the ClojureWerkz Team

Validateur 2.1.0 Is Released

TL;DR

Validateur is a functional validations library inspired by Ruby’s ActiveModel. Validateur 2.1 is a minor feature release.

Changes Between 2.0.0 and 2.1.0

Multi-field Support For Presence Validator

presence-of validator now supports validation over multiple (all or any) fields:

1
2
3
4
5
;; both fields must be non-nil
(vr/presence-of #{:name :msg})

;; either field must be non-nil
(vr/presence-of #{:name :msg} :any true)

Contributed by Radosław Piliszek.

Better ClojureScript Support

Validateur no longer uses crossovers which are deprecated in lein-cljsbuild.

Contributed by Radosław Piliszek.

Full Change Log

Validateur change log is available on GitHub.

Validateur is a ClojureWerkz Project

Validateur is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Monger, a Clojure MongoDB client for a more civilized age
  • Elastisch, a minimalistic Clojure client for ElasticSearch
  • Cassaforte, a Clojure Cassandra client built around CQL
  • Neocons, a client for the Neo4J REST API
  • Welle, a Riak client with batteries included
  • Quartzite, a powerful scheduling library

and several others. If you like Validateur, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About The Author

Michael on behalf of the ClojureWerkz Team

Elastisch 2.0.0-rc1 Is Released

TL;DR

Elastisch is a battle tested, small but feature rich and well documented Clojure client for ElasticSearch. It supports virtually every Elastic Search feature and has solid documentation.

2.0.0-rc1 is a release candidate of Elastisch 2.0, which focuses on the new features in ElasticSearch 1.1 and introduces major API improvements, including a breaking change.

Changes between Elastisch 2.0.0-beta5 and 2.0.0-rc1

Connection/Client As Explicit Argument

Starting with Elastisch 2.0.0-rc1, connection (client) is no longer a shared dynamic var but rather is an explicit argument that relevant API functions accept.

Before the change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(ns clojurewerkz.elastisch.docs.examples
  (:require [clojurewerkz.elastisch.rest  :as esr]
            [clojurewerkz.elastisch.rest.index :as esi]
            [clojurewerkz.elastisch.rest.document :as esd]))

(defn -main
  [& args]
  (esr/connect! "http://127.0.0.1:9200")
  (let [mapping-types {"person" {:properties {:username   {:type "string" :store "yes"}
                                              :first-name {:type "string" :store "yes"}
                                              :last-name  {:type "string"}
                                              :age        {:type "integer"}
                                              :title      {:type "string" :analyzer "snowball"}
                                              :planet     {:type "string"}
                                              :biography  {:type "string" :analyzer "snowball" :term_vector "with_positions_offsets"}}}}
        doc           {:username "happyjoe" :first-name "Joe" :last-name "Smith" :age 30 :title "Teh Boss" :planet "Earth" :biography "N/A"}]
    (esi/create "myapp2_development" :mappings mapping-types)
    (esd/create "myapp2_development" "person" doc)))

After the change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(ns clojurewerkz.elastisch.docs.examples
  (:require [clojurewerkz.elastisch.rest  :as esr]
            [clojurewerkz.elastisch.rest.index :as esi]
            [clojurewerkz.elastisch.rest.document :as esd]))

(defn -main
  [& args]
  (let [conn          (esr/connect "http://127.0.0.1:9200")
        mapping-types {"person" {:properties {:username   {:type "string" :store "yes"}
                                              :first-name {:type "string" :store "yes"}
                                              :last-name  {:type "string"}
                                              :age        {:type "integer"}
                                              :title      {:type "string" :analyzer "snowball"}
                                              :planet     {:type "string"}
                                              :biography  {:type "string" :analyzer "snowball" :term_vector "with_positions_offsets"}}}}
        doc           {:username "happyjoe" :first-name "Joe" :last-name "Smith" :age 30 :title "Teh Boss" :planet "Earth" :biography "N/A"}]
    (esi/create conn "myapp2_development" :mappings mapping-types)
    (esd/create conn "myapp2_development" "person" doc)))

Dynamic var reliance has been a major complaint of Clojure users for quite some time and 2.0 is the right time to fix this.

Changes between Elastisch 2.0.0-beta4 and 2.0.0-beta5

Response Helpers Compatible With ES 1.1

clojurewerkz.elastisch.rest.response/created? and clojurewerkz.elastisch.native.response/created? were adapted for recent ES releases.

Contributed by Oliver McCormack (The Climate Corporation).

ElasticSearch Client Update

ElasticSearch client has been upgraded to 1.1.1.

Changes between Elastisch 2.0.0-beta3 and 2.0.0-beta4

Options As Maps

Elastisch has tranditionally accepted options as (pseudo) keywrod arguments, e.g.

1
(doc/search index-name mapping-type :query (q/term :biography "say"))

Starting with 2.0.0-beta4, passing a single map of arguments is now also supported by nearly all document, index, admin and percolation functions:

1
(doc/search index-name mapping-type {:query (q/term :biography "say")})

As a new design rule, all new API elements (e.g. aggregations) will accept a single map of options.

GH issue: #59.

Percolation of Existing Documents (REST API)

REST API client now supports percolation of existing documents:

1
2
3
(require '[clojurewerkz.elastisch.rest.percolation :as pcl])

(pcl/percolate-existing "articles" "article" "123")

Changes between Elastisch 2.0.0-beta2 and 2.0.0-beta3

ElasticSearch Client Update

ElasticSearch client has been upgraded to 1.1.0.

Clojure 1.6

Elastisch now depends on org.clojure/clojure version 1.6.0. It is still compatible with Clojure 1.4 and if your project.clj depends on a different version, it will be used, but 1.6 is the default now.

Type Exists Operation

types-exists support in both rest and native clients:

1
2
3
(require '[clojurewerkz.elastisch.rest.index :as esi])

(esi/type-exists? "an-index" "a-type")

Contributed by Halit Olali.

Changes between Elastisch 2.0.0-beta1 and 2.0.0-beta2

(Improved) Aggregation Support

Elastisch 2.0 features multiple convenience functions for working with ElasticSearch aggregations.

clojurewerkz.elastisch.aggregation is a new namespace that contains helper functions that produce various types of aggregations. Just like clojurewerkz.elastisch.query, all of the functions return maps and are optional.

clojurewerkz.elastisch.rest.response/aggregations-from is a new function that returns aggregations from a search response:

1
2
3
4
5
6
7
8
9
10
11
12
(require '[clojurewerkz.elastisch.rest.document :as doc])
(require '[clojurewerkz.elastisch.query :as q])
(require '[clojurewerkz.elastisch.aggregation :as a])
(require '[clojurewerkz.elastisch.rest.response :refer [aggregations-from]])

(let [index-name   "people"
        mapping-type "person"
        response     (doc/search index-name mapping-type
                                 :query (q/match-all)
                                 :aggregations {:min_age (a/min "age")})
        agg          (aggregation-from response :min_age)]
    (is (= {:value 22.0} agg)))

Aggregations support is primarily focused on REST client at the moment.

clj-http Update

clj-http dependency has been upgraded to version 0.9.1.

Changes between Elastisch 1.4.0 and 2.0.0-beta1

ElasticSearch 1.0 Compatibility

Main goal of Elastisch 2.0 is ElasticSearch 2.0 compatibility. This includes minor API changes (in line with ElasticSearch 1.0 API and terminology changes) and moderate internal modifications.

Support for cluster nodes stats and info REST APIs

clojureworkz.elastisch.rest.admin/nodes-info and clojureworkz.elastisch.rest.admin/nodes-stats are new administrative functions that provide access to ElasticSearch cluster stats and node info.

Examples:

1
2
3
4
5
6
7
8
9
(require '[clojurewerkz.elastisch.rest.admin :as admin])

(admin/nodes-stats)
(admin/nodes-stats :nodes "_all")
(admin/nodes-stats :nodes ["node1" "node2"] ["indices" "os" "plugins"])

(admin/nodes-info)
(admin/nodes-info :nodes "_all")
(admin/nodes-info :nodes ["node1" "node2"] ["indices" "os" "plugins"])

See ElasticSearch nodes stats documentation, nodes info page, and node specification page for more info.

Contributed by Joachim De Beule.

Support for _cluster/state REST API

Added (clojureworkz.elastisch.rest.admin/cluster-state & {:as params})

Examples:

1
2
3
4
(require '[clojurewerkz.elastisch.rest.admin :as admin])

(admin/cluster-state)
(admin/cluster-state :filter_nodes true)

See ElasticSearch documentation for more info.

Contributed by Joachim De Beule.

Support for _cluster/health REST API

Added (clojureworkz.elastisch.rest.admin/cluster-health & {:as params})

Example:

1
2
3
4
5
6
(require '[clojurewerkz.elastisch.rest.admin :as admin])

(admin/cluster-health)
(admin/cluster-health :index "index1")
(admin/cluster-health :index ["index1","index2"])
(admin/cluster-health :index "index1" :pretty true :level "indices")

See ElasticSearch documentation for more info.

Contributed by Joachim De Beule.

Support for analyze in REST API client

Added (doc/analyze text & {:as params})

See ElasticSearch documentation for more info.

Examples:

1
2
3
4
5
6
7
(require '[clojurewerkz.elastisch.rest.document :as doc])

(doc/analyze "foo bar baz")
(doc/analyze "foo bar baz" :index "some-index-name")
(doc/analyze "foo bar baz" :analyzer "whitespace")
(doc/analyze "foo bar baz" :tokenizer "keyword" :filters "lowercase")
(doc/analyze "foo bar baz" :index "some-index-name" :field "some-field-name")

Contributed by Joachim De Beule

Query String Escaping

clojurewerkz.elastisch.query/query-string accepts a new option, :escape-with, which is a function that performs escaping of special characters in query string queries.

By default clojurewerkz.elastisch.escape/escape-query-string-characters is used.

Contributed by Ben Reinhart (Groupon).

ElasticSearch Native Client Upgrade

Elastisch now depends on ElasticSearch native client version 1.0.1.

clj-http Update

clj-http dependency has been upgraded to version 0.9.0.

Full Change Log

Elastisch change log is available on GitHub.

Thank You, Contributors

Kudos to Halit Olali, shmish111, and Richie Vos for contributing to the 2.0 release.

Elastisch is a ClojureWerkz Project

Elastisch is part of the group of libraries known as ClojureWerkz, together with

  • Langohr, a Clojure client for RabbitMQ that embraces the AMQP 0.9.1 model
  • Monger, a Clojure MongoDB client for a more civilized age
  • Cassaforte, a Clojure Cassandra client
  • Titanium, a Clojure graph library
  • Neocons, a client for the Neo4J REST API
  • Welle, a Riak client with batteries included
  • Quartzite, a powerful scheduling library

and several others. If you like Elastisch, you may also like our other projects.

Let us know what you think on Twitter or on the Clojure mailing list.

About the Author

Michael on behalf of the ClojureWerkz Team