Created
July 16, 2012 17:32
-
-
Save martintrojer/3123920 to your computer and use it in GitHub Desktop.
core.logic datomic query blog2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(do | |
(defrel id-first p1 p2) | |
(defrel id-email p1 p2) | |
(defrel id2-email p1 p2) | |
(defrel id2-height p1 p2) | |
(fact id-first 1 "John") | |
(fact id-email 1 "[email protected]") | |
(fact id-first 2 "Jane") | |
(fact id-email 2 "[email protected]") | |
(fact id2-email 100 "[email protected]") | |
(fact id2-height 100 73) | |
(fact id2-email 101 "[email protected]") | |
(fact id2-height 101 71) | |
(run* [q] | |
(fresh [id id2 fst email height] | |
(id-first id fst) | |
(id-email id email) | |
(id2-email id2 email) | |
(id2-height id2 height) | |
(== q [fst height])))) | |
;; (["John" 71] ["Jane" 73]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(do | |
(defquery join [:first :height] [[:last :first :email] [:email :height]]) | |
(fact join-last-first-email "Doe" "John" "[email protected]") | |
(fact join-last-first-email "Doe" "Jane" "[email protected]") | |
(fact join-email-height "[email protected]" 73) | |
(fact join-email-height "[email protected]" 71) | |
(join-run)) | |
;; (["Jane" 73] ["John" 71]) | |
(do | |
(defquery join2 [:firstName :height] [[:e1 :firstName] [:e1 :email] [:e2 :email] [:e2 :height]]) | |
(fact join2-e1-firstName 1 "John") | |
(fact join2-e1-email 1 "[email protected]") | |
(fact join2-e1-firstName 2 "Jane") | |
(fact join2-e1-email 2 "[email protected]") | |
(fact join2-e2-email 100 "[email protected]") | |
(fact join2-e2-height 100 73) | |
(fact join2-e2-email 101 "[email protected]") | |
(fact join2-e2-height 101 71) | |
(join2-run)) | |
;; (["John" 71] ["Jane" 73]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defmacro defquery [relname find rels] | |
(let [idx-syms (->> (repeatedly gensym) (map #(with-meta % {:index :t}))) | |
relname (fn [r] (symbol (str relname "-" (->> r (map name) (interpose "-") (reduce str))))) | |
lvars (fn [r] (->> r (map name) (map symbol))) | |
defrels (for [r rels] `(defrel ~(relname r) ~@(take (count r) idx-syms))) | |
joins (for [r rels] `(~(relname r) ~@(lvars r)))] | |
`(do | |
~@defrels | |
(defn ~(relname [:run]) [] | |
(run* [q#] | |
(fresh [~@(set (mapcat lvars rels))] | |
~@joins | |
(== q# [~@(lvars find)]))))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defrel last-first-email p1 p2 p3) | |
(defrel email-height p1 p2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(fact last-first-email "Doe" "John" "[email protected]") | |
(fact last-first-email "Doe" "Jane" "[email protected]") | |
(fact email-height "[email protected]" 73) | |
(fact email-height "[email protected]" 71) | |
(run* [q] | |
(fresh [fst email height] | |
(last-first-email (lvar) fst email) | |
(email-height email height) | |
(== q [fst height]))) | |
;; (["Jane" 73] ["John" 71]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn join-test2 [xs ys] | |
;; setup the relations | |
(defquery join [:first :height] [[:last :first :email] [:email :height]]) | |
;; load the facts | |
(time | |
(do | |
(doseq [x xs] (apply fact join-last-first-email x)) | |
(doseq [y ys] (apply fact join-email-height y)))) | |
;; run the query | |
(time | |
(join-run))) | |
(defn bench [n f] | |
(let [rand-str #(str (java.util.UUID/randomUUID)) | |
emails (repeatedly n rand-str) | |
name-email (reduce (fn [res em] | |
(conj res (vector (rand-str) (rand-str) em))) | |
[] emails) | |
email-height (reduce (fn [res em] | |
(conj res (vector em (rand-int 100)))) | |
[] emails)] | |
(time (count (f name-email email-height))))) | |
(bench 5000 join-test2) | |
;; "Elapsed time: 287.275 msecs" (loading the data) | |
;; "Elapsed time: 127.188 msecs" (running the query) | |
;; "Elapsed time: 415.466 msecs" (total) | |
;; 5000 | |
;; =================================================== | |
;; Results from previous post | |
(bench 5000 (partial q '[:find ?first ?height | |
:in [[?last ?first ?email]] [[?email ?height]]])) | |
;; "Elapsed time: 14757.248824 msecs" | |
;; 5000 | |
(bench 5000 (partial q '[:find ?first ?height | |
:in $a $b | |
:where [$a ?last ?first ?email] [$b ?email ?height]])) | |
;; "Elapsed time: 10.869 msecs" | |
;; 5000 | |
(bench 5000 join-test) | |
;; "Elapsed time: 185.604 msecs" | |
;; 5000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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]]) | |
;; #<HashSet [["Jane" 73], ["John" 71]]> |
Sure, you can move the defrels out, doesn't impact the the speed much. I do need to load the facts in the "query function" tho, like you said, that's the use-case I'm going for here.
Why do you need to? Many improvements to core.logic are necessary for this to work well for larger amounts of data.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Putting defrel in join-test2 doesn't make much sense. In reality you would not load the facts in this way every time, but I guess that makes sense if you want to compare with Datomic's neato functionality.