How to retrive in Clojure from a vector of maps (Elasticseach buckets) the doc_count of a given key

63 Views Asked by At

From a Clojure Elasticsearch aggregation query, I have a buckets vector of maps like the following where the key is a numerical identifier and the doc_count is the number of occurrences.

:buckets [{:key 14768496, :doc_count 464} {:key 14761312, :doc_count 440} {:key 14764921, :doc_count 412}]

Given a value like 14768496 I would like to be able to retrieve the doc_count, here 464.

3

There are 3 best solutions below

1
Andreas Guther On

While crafting the question I came across the following solution which I now want to share since it took me a while to find the right approach.

(def accounts (apply hash-map
                      (mapcat
                        #(vector (% :key) (% :doc_count))
                        buckets)))

This produces the following map:

{14768496 464, 14761312 440, 14764921 412}

Now the retrieval is straightforward:

(println (accounts 14768496))
0
dorab On

A different way of creating your accounts map:

user> (def buckets [{:key 14768496, :doc_count 464} {:key 14761312, :doc_count 440} {:key 14764921, :doc_count 412}])
#'user/buckets
user> (def accounts (zipmap (map :key buckets) (map :doc_count buckets)))
#'user/accounts

Alternatively ...

user> (defn find-doc-count [k buckets] (some #(when (= (:key %) k) (:doc_count %)) buckets))
#'user/find-doc-count
user> (find-doc-count 14768496 buckets)
464
2
Sean Corfield On

I provided some feedback on the OP's own answer but figured it was worth providing as an answer in its own right:

user> (def buckets [{:key 14768496, :doc_count 464} {:key 14761312, :doc_count 440} {:key 14764921, :doc_count 412}])
#'user/buckets
user=> (def accounts (into {} (map (juxt :key :doc_count)) buckets))
#'user/accounts

This uses the transducer-producing arity of map as the "xform" argument to into so it avoids creating any intermediate lazy sequences.

You could also do (into {} (map (juxt :key :doc_count) buckets)) which will produce a lazy sequence of vector pairs (of the key and the document count), and then "pour" it into an empty hash map.

juxt returns a function of one parameter that produces a vector from the application of each argument (the functions passed to juxt) to that parameter:

user=> ((juxt inc dec) 42)
[43 41]