Skip to content

Instantly share code, notes, and snippets.

@danielneal
Last active June 9, 2019 18:02
Show Gist options
  • Save danielneal/081b320631da733f66d9e49b60af2341 to your computer and use it in GitHub Desktop.
Save danielneal/081b320631da733f66d9e49b60af2341 to your computer and use it in GitHub Desktop.
Minimal query for maps
(ns query.core)
(defn paths
([q]
(paths [] {} q))
([current-path m q]
(letfn [(paths-map
[current-path m q]
(apply merge (for [[k v] q]
(paths (conj current-path k) {} v))))
(paths-vec
[current-path m q]
(apply merge (for [v q]
(if (map? v)
(paths-map current-path {} v)
(paths (conj current-path v) {} v)))))]
(cond
(map? q) (paths-map current-path m q)
(vector? q) (paths-vec current-path m q)
:else {q current-path}))))
(defn query-fn
[q]
(let [paths (paths q)]
(fn [db]
(reduce-kv (fn [m k v] (assoc m k (get-in db v))) {} paths))))
(defn query
[db q]
(let [f (query-fn q)]
(f db)))
(comment
(query
{:products/by-id {1 {:product/id 1
:product/sku "FINMOD001"
:product/nutrition {:energy "100kcal"
:salt "1g"}}}}
{:products/by-id {1 [:product/id :product/sku :product/nutrition]}})
#:product{:id 1, :sku "FINMOD001", :nutrition {:energy "100kcal", :salt "1g"}})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment