• Stars
    star
    261
  • Rank 156,630 (Top 4 %)
  • Language
    Clojure
  • Created almost 8 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Elasticsearch client for Clojure (built on new ES 8.x java client)

spandex

Clojars Project

Elasticsearch new low level rest-client wrapper

Why?

To quote "State of the official Elasticsearch Java clients"

The Java REST client is the future for Java users of Elasticsearch.

Because the legacy native client is a bit of a nightmare to deal with (for many reasons) and the new REST client is quite capable and fast too, see "Benchmarking REST client and transport client"

Not to mention it supports some interesting features:

  • compatibility with any Elasticsearch version

  • load balancing across all available nodes

  • failover in case of node failures and upon specific response codes

  • failed connection penalization

  • persistent connections

  • trace logging of requests and responses

  • optional automatic discovery of cluster nodes (also known as sniffing)

Goals

  • Be minimal & performant

  • RING inspired

  • All "exotic" features should be optional

  • Not a giant DSL over another DSL, just maps everywhere. Read ElasticSearch doc -> done, not another layer of indirection

  • Provide minimal (and optional) utils to do the boring stuff (bulk, scroll queries, compose urls)

  • Can do async via simple callbacks based api or core.async

  • Provide specs

Setup

(require '[qbits.spandex :as s])

(def c (s/client {:hosts ["http://127.0.0.1:9200" "https://foo2:3838"]}))

;; add optional sniffer
(def s (s/sniffer c {... options ...}))

Work with https via ssh tunneling

First setup and make sure that you have appropriate access to the host via tunneling.

e.g. Add/edit your ~/.ssh/config to look something like

# Example of tunneling in ~/.ssh/config
# .. more config
Host my-aws-elasticsearch-host 
  HostName 10.123.345.456
  User ec2-user
  IdentitiesOnly yes
  IdentityFile ~/.ssh/my-aws-elasticsearch.pem
  LocalForward 9200 vpc-my-aws-elasticsearch-host-lb43i.us-east-1.es.amazonaws.com:443
  ServerAliveInterval 240
# .. more config

You can then start ssh tunneling with

# see manpage of `ssh` for more details
ssh -oStrictHostKeyChecking=no my-aws-elasticsearch-host -N 

Then you can create your client using the following :http-client options like

;; if you are using tunnelling to host in AWS e.g.
(def client (s/client {:hosts ["https://localhost:9200"]
                       :http-client {:ssl-context (client/ssl-context-trust-all)
                                     :ssl-noop-hostname-verifier? true}}))

Constructing URLs

Most of spandex request functions take a request map as parameter. The :url key differs a bit from the original RING spec, it allows to pass a raw string but also a sequence (potentially 2d) of encodable things, keywords, .toString'able objects that make sense or nil (which could be caused by a missing :url key).

(s/request c {:url [:foo :bar :_search] ...})
(s/request c {:url [:foo [:bar :something "more"] :_search] ...})
(s/request c {:url :_search ...})
(s/request c {:url "/index/_search" ...})
(s/request c {:url (java.util.UUID/randomUUID) ...})
(s/request c {...}) ;; defaults to "/"

Blocking requests

(s/request c {:url [:entries :entry :_search]
              :method :get
              :body {:query {:match_all {}}}})

>> {:body {:_index "entries", :_type "entry", :_id "AVkDDJvdkd2OsNWu4oYk", :_version 1, :_shards {:total 2, :successful 1, :failed 0}, :created true}, :status 201, :headers {"Content-Type" "application/json; charset=UTF-8", "Content-Length" "141"}, :host #object[org.apache.http.HttpHost 0x62b90fad "http://127.0.0.1:9200"]}

Async requests (callbacks)

(s/request-async c {:url "/urls/url/"
                    :method :get
                    :body {:query {:match {:message "this is a test"}}}
                    :success (fn [response-as-clj] ... )
                    :error (fn [ex] :boom)})

Async requests: core.async/promise-chan

(async/<!! (s/request-chan c {:url "/urls/url/"
                              :method :get
                              :body {:query {:match {:message "this is a test"}}}}))

Scrolling

Scrolling via core.async (fully NIO internally), interruptible if you async/close! the returned chan.

(async/go
  (let [ch (s/scroll-chan client {:url "/foo/_search" :body {:query {:match_all {}}}})]
    (loop []
      (when-let [page (async/<! ch)]
        (do-something-with-page page)
        (recur)))))

Bulk requests scheduling

"Faux streaming" of _bulk requests (flushes bulk request after configurable interval or threshold. Uses request-chan internally, so it's quite cheap.

(let [{:keys [input-ch output-ch]} (bulk-chan client {:flush-threshold 100
                                                      :flush-interval 5000
                                                      :max-concurrent-requests 3})]
  ;; happily takes a sequence of actions or single fragments
  (async/put! input-ch [{:delete {:_index "foo" :_id "1234"}} {:_index :bar} {:create {...}}])
  (async/put! input-ch {"delete" {"_index" "website" "_type" "blog" "_id" "123"}}))

;; setup an response consumer (we just want to make sure we don't clog this channel)
(future
  (loop []
    (when (async/<!! (:output-ch c))
      (recur))))

Installation

Clojars Project

API Docs

QuickDoc

Or the clj.specs if that's your thing:

Running the tests

clj -X:test qbits.spandex.test-runner/run

clj -X:test qbits.spandex-test-runner/run

Patreon

If you wish to support the work on this project you can do this via my patreon page.

License

Copyright © 2018 Max Penet

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

More Repositories

1

alia

High performance Cassandra client for clojure
Clojure
246
star
2

jet

[not maintained, use at own risk] Jetty9 ring server adapter with WebSocket support via core.async and Jetty9 based HTTP & WebSocket clients (jvm based, no cljs)
Clojure
167
star
3

tape

Chronicle Queue helpers
Clojure
134
star
4

hirundo

Helidon 4.x RING adapter - using loom/java21+
Clojure
100
star
5

hayt

CQL3 DSL for Clojure
Clojure
74
star
6

clojure-snippets

yasnippet 0.7.0+ snippets for clojure
Emacs Lisp
58
star
7

auspex

Mini wrapper over java CompletableFuture with a manifold deferred after-taste
Clojure
42
star
8

knit

Thin wrapper around Java Executors/Threads, including configurable `future`, `c.core/thread`, and `future-call`
HTML
33
star
9

pact

clojure.spec to json-schema generation library
Clojure
25
star
10

thorn

Homoglyph/IDN homograph detection/handling - Clojure port of python confusable_homoglyphs
Clojure
22
star
11

flex

Using TCP congestion control methods to find/set real limits of a system over time
Clojure
20
star
12

sextant

Offline location geocoder/reverse geocoder from GeoName datasets
Java
18
star
13

ex

Exception net
Clojure
17
star
14

casyn

Clojure client for Cassandra using Thrift AsyncClient - For a better/more robust client using CQL3 see https://github.com/mpenet/alia
Clojure
17
star
15

spex

Utils/Helpers for clojure spec
Clojure
16
star
16

checkmate

All your fails are belong to us
Clojure
14
star
17

jilch

Clojure ZeroMQ Library using Jeromq (drop in replacement for zilch)
Clojure
12
star
18

emax

my .emacs.d
Emacs Lisp
12
star
19

esearch

Elastic Search client for Clojure
Clojure
11
star
20

eddy

Jetty11+ wrapper/adapter for clojure
Clojure
7
star
21

caffeine

Simple wrapper for com.github.ben-manes.caffeine/caffeine
Clojure
7
star
22

nippy-lz4

LZ4 compression for ptaoussanis/nippy
Clojure
6
star
23

commons

stuff
Clojure
5
star
24

bootstrap-mod

Modular twitter/bootstrap
5
star
25

thera

Deprecated: give a try to mpenet/casyn (thrift) or mpenet/alia (CQL3) instead- Clojure Cassandra CQL client
Clojure
5
star
26

tardis

Minimalistic library to manage Type 1 UUIDs (time based) - com.eaio.uuid wrapper
Clojure
4
star
27

grease

Some utils for performance critical situations
Java
4
star
28

ash

Simple, extensible irc bot based on pircbotx
Clojure
4
star
29

xmonad

(minimalistic) xmonad/trayer/xmobar config with a zenburn'ish theme. Supports both t410s and xps13 sputnik
Shell
4
star
30

sextant_

Geo location utility functions
Clojure
3
star
31

unilog-sentry

Sentry appender for pyr/unilog
Clojure
3
star
32

ring-spec

clojure.specs for the latest RING
Clojure
2
star
33

tempel-clojure

tempel snippets for clojure
Emacs Lisp
2
star
34

quiver

Clojure 1.5 new threading macros as a library
Clojure
2
star
35

softshake-talk

2
star
36

mehub

GitHub personal page (static, js/ClojureScript based)
JavaScript
2
star
37

pod

Walks like an atom, and quacks like an atom but...
Clojure
2
star
38

dam

Redis/LUA backed rate limiting for clojure
Clojure
2
star
39

sibilant-mode

sibilant emacs mode
Emacs Lisp
2
star
40

padded-modeline

Padded emacs modeline
Emacs Lisp
1
star
41

bug-playground

where bugs multiply and thrive
Clojure
1
star
42

record-utils

Clojure
1
star