Skip to content

Instantly share code, notes, and snippets.

@thickey
Forked from stuarthalloway/gist:2645453
Created October 3, 2012 14:29
Show Gist options
  • Save thickey/3827215 to your computer and use it in GitHub Desktop.
Save thickey/3827215 to your computer and use it in GitHub Desktop.
Datomic queries against Clojure collections
;; Datomic example code
(use '[datomic.api :only (db q) :as d])
;; ?answer binds a scalar
(q '[:find ?answer :in ?answer]
42)
;; of course you can bind more than one of anything
(q '[:find ?last ?first :in ?last ?first]
"Doe" "John")
;; [?last ?first] binds a tuple
(q '[:find ?last ?first :in [?last ?first]]
["Doe" "John"])
;; [?first ...] binds a collection
(q '[:find ?first
:in [?first ...]]
["John" "Jane" "Phineas"])
;; [[?first ?last]] binds a relation
(q '[:find ?first
:in [[?first ?last]]]
[["John" "Doe"]
["Jane" "Doe"]])
;; a database binding name starts with $ instead of ?
;; any relation with 4-tuples E/A/V/T can act as a database
;; so in Datomic, you can mock a database with a list of lists
(q '[:find ?first
:in $db
:where [$db _ :firstName ?first]]
[[1 :firstName "John"]])
;; same as previous, but omit $db for single-database query
;; any relation with 4-tuples eavt can act as a database
(q '[:find ?first
:where [_ :firstName ?first]]
[[1 :firstName "John" 42]
[1 :lastName "Doe" 42]])
;; simple in-memory join, two tuple bindings
(q '[:find ?first ?height
:in [?last ?first ?email] [?email ?height]]
["Doe" "John" "[email protected]"]
["[email protected]" 71])
;; simple in-memory join, two relation bindings
;; see next example for a faster approach
(q '[:find ?first ?height
:in [[?last ?first ?email]] [[?email ?height]]]
[["Doe" "John" "[email protected]"]
["Doe" "Jane" "[email protected]"]]
[["[email protected]" 73]
["[email protected]" 71]])
;; same as previous example, but with database expressions
;; runs faster than relation bindings (as of July 2012)
(q '[:find ?first ?height
:in $a $b
:where [$a ?last ?first ?email]
[$b ?email ?height]]
[["Doe" "John" "[email protected]"]
["Doe" "Jane" "[email protected]"]]
[["[email protected]" 73]
["[email protected]" 71]])
;; simple in-memory join, two database bindings
(q '[:find ?first ?height
:in $db1 $db2
:where [$db1 ?e1 :firstName ?first]
[$db1 ?e1 :email ?email]
[$db2 ?e2 :email ?email]
[$db2 ?e2 :height ?height]]
[[1 :firstName "John"]
[1 :email "[email protected]"]
[2 :firstName "Jane"]
[2 :email "[email protected]"]]
[[100 :email "[email protected]"]
[100 :height 73]
[101 :email "[email protected]"]
[101 :height 71]])
;; compare to http://stackoverflow.com/questions/3717939/iterating-and-processing-an-arraylist
(q '[:find ?car ?speed
:in [[?car ?speed]]
:where [(> ?speed 100)]]
[["Stock" 225]
["Spud" 80]
["Rocket" 400]
["Stock" 225]
["Clunker" 40]])
;; compare to http://stackoverflow.com/questions/109383/how-to-sort-a-mapkey-value-on-the-values-in-java
(->> (q '[:find ?k ?v
:in [[?k ?v] ...]]
{:D 67.3 :A 99.5 :B 67.4 :C 67.5})
(sort-by second))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment