Skip to content

Instantly share code, notes, and snippets.

@bostonaholic
Last active October 22, 2018 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bostonaholic/30e31f4620804632d3c8 to your computer and use it in GitHub Desktop.
Save bostonaholic/30e31f4620804632d3c8 to your computer and use it in GitHub Desktop.
Showing datomic or-join searches
(require '[clojure.test :refer [is]])
(require '[datomic.api :as d])
(def url "datomic:mem://localhost:4334/test")
(d/create-database url)
(def conn (d/connect url))
(def schema [{:db/id #db/id[:db.part/db]
:db/ident :person/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :person/address
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :address/street
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :address/zip
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}])
(d/transact conn schema)
(def alice {:db/id #db/id[:db.part/user -1]
:person/name "Alice"
:person/address {:db/id #db/id[:db.part/user -10]
:address/street "123 Fake St."
:address/zip "12345"}})
(def bob {:db/id #db/id[:db.part/user -2]
:person/name "Bob"
:person/address {:db/id #db/id[:db.part/user -20]
:address/street "456 Fake St."
:address/zip "67890"}})
(def charles {:db/id #db/id[:db.part/user -3]
:person/name "Charles"
:person/address {:db/id #db/id[:db.part/user -30]
:address/street "123 Bob St."
:address/zip "67890"}})
(def danielle {:db/id #db/id[:db.part/user -4]
:person/name "Danielle"
:person/address {:db/id #db/id[:db.part/user -40]
:address/street "123 Something St."
:address/zip "76543"}})
(d/transact conn [alice bob charles danielle])
(defn search [db query zips]
(d/q '[:find [(pull ?person [* {:person/address [*]}]) ...]
:in $ ?pattern [?zip ...]
:where
(or-join [?person ?pattern ?zip]
(and [?person :person/address ?address]
[?address :address/zip ?zip])
(and [?person :person/name ?name]
[(re-find ?pattern ?name)])
(and [?person :person/address ?address]
[?address :address/street ?street]
[(re-find ?pattern ?street)]))]
db
(re-pattern (str "(?i).*" query ".*"))
zips))
(defn compare-names [expected actual]
(is (= (set (map :person/name expected))
(set (map :person/name actual)))))
(compare-names (list bob charles danielle)
(search (d/db conn) "bob" ["67890" "76543"]))
(comment
"Expected:"
"bob, becuase his name matches the query."
"charles, because his street matches the query."
"danielle, because her zip is in the list of zip codes.")
(compare-names (list danielle)
(search (d/db conn) "foo" ["76543"]))
(comment
"Expected:"
"danielle, because her zip is in the list of zip codes.")
(compare-names (list alice)
(search (d/db conn) "alice" []))
(comment
"Expected:"
"alice, because her name matches the query.")
(compare-names (list alice)
(search (d/db conn) "alice" [""]))
(comment "This works!?")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment