#+TITLE: Minimal clojurescript project demoing datalog queries * Getting started To work with the code interactively jack into the project in your IDE of choice select "figwheel-main" as the build tool and dev as the build. Alternatively start a repl from the command line with #+BEGIN_SRC sh clojure -m figwheel.main --build dev --repl #+END_SRC * Intro to datalog First import datascript which is a client side version of datalog, see datomic crux datalevin and datahike for other datalog database. #+BEGIN_SRC clojurescript :tangle ./src/test.cljs (ns core.demo (:require [datascript.core :as d])) #+END_SRC See the extensive comments in the src code for a working example, also watch / read these for a good intro. https://www.youtube.com/watch?v=oo-7mN9WXTw http://www.learndatalogtoday.org/ https://udayv.com/clojurescript/clojure/2016/04/28/datascript101/ Blog of the dev who makes datascript https://tonsky.me/blog/the-web-after-tomorrow/ ** Creating a DATABASE Datalog databases can be schema less but a lot of the power comes from creating a schema specifying uniqueness and relations on the stored fields. You can create a new database using create-conn as below then empty hash map is simply a blank schema, #+BEGIN_SRC clojurescript :tangle ./src/test.cljs (def demo-conn (d/create-conn {})) #+END_SRC Using the connection we can just start inserting data, using standard hash maps and lists structures, we always specify the attribute and the value when transacting. #+BEGIN_SRC clojurescript :tangle ./src/test.cljs (d/transact! demo-conn [{:user/name "Brooke" :user/img "me.jpg"} {:user/name "Kalvin" :user/img "you.jpg"}]) #+END_SRC *** Using a Schema In this example we are saying name is unique and rooms has a many to one relationship, when we transact data will be inserted even if its not in the schema but rules stop things like duplicates from happening. #+BEGIN_SRC clojurescript :tangle ./src/test.cljs (def schema {:user/name {:db/unique :db.unique/identity} :user/rooms {:db/cardinality :db.cardinality/many :db/valueType :db.type/ref}}) (def demo-conn (d/create-conn schema)) #+END_SRC Transacting this data would mean Brooke would be inserted once but the image will be updated to =you.jpg= #+BEGIN_SRC clojurescript :tangle ./src/test.cljc (d/transact! demo-conn [{:user/name "Brooke" :user/img "you.jpg"}]) #+END_SRC ** Querying the databases There are three types of queries in datalog entity lookup's pulling a tree of data or querying with =d/q=. *** Looking up an entity =d/entity= is used to find the entity id, using any unique piece of data for example the user =Brooke= exists once so the entity db/id will be returned which can be used for further queries. #+BEGIN_SRC clojurescript :tangle ./src/test.cljc (d/entity @demo-conn [:user/name "Brooke"]) #+END_SRC *** Pull a tree of data Pull is used with entity id's once you know the entity you can specify what data you want to view ='[*]= being the most common looking up all keys, you can also specify the attributes your interested in looking up including there relations to make a more specific view. #+BEGIN_SRC clojurescript :tangle ./src/test.cljc (d/pull @demo-conn '[*] 1) (d/pull @demo-conn '[:user/name :user/rooms] 1) #+END_SRC *** Querying your dataset Querying in datalog is all about binding variables to your entities attributes and values which you can use in you conditions or to return in the result set. In this example we return the user-id and user/name in the find clause which we looked up in the where clause by finding all attributes =:user/name= the binding the entity id and username to variables on each match to display in the find clause. #+BEGIN_SRC clojurescript :tangle ./src/test.cljc (d/q '[:find ?user-entity ?user-name :where [?user-entity :user/name ?user-name]] @demo-conn) #+END_SRC Write some more as needed better examples in the src code.