diff --git a/reagent-reitit-demo/deps.edn b/reagent-reitit-demo/deps.edn index 36c0fcb..3c0105e 100644 --- a/reagent-reitit-demo/deps.edn +++ b/reagent-reitit-demo/deps.edn @@ -8,14 +8,17 @@ reagent {:mvn/version "0.9.1"} reagent-utils {:mvn/version "0.3.3"} olymk2/cl-org {:git/url "https://gitlab.com/olymk2/cl-org.git" - :sha "b5a084e8003298a1eb79ecd65ea454970c16b123"} + :sha "2bb6f41b317749ea3467987ea57ee7807b59d921"} ;;routing metosin/reitit {:mvn/version "0.5.10"} metosin/reitit-spec {:mvn/version "0.5.10"} metosin/reitit-frontend {:mvn/version "0.5.10"} ;; interactive code snippets - viebel/klipse {:mvn/version "7.10.4"} + ;;viebel/klipse {:mvn/version "7.10.4"} + viebel/klipse {:mvn/version "7.9.1"} + datascript {:mvn/version "1.0.0"} + com.bhauman/figwheel-main {:mvn/version "0.2.11"}} :paths ["src" "resources"] diff --git a/reagent-reitit-demo/dev.cljs.edn b/reagent-reitit-demo/dev.cljs.edn index e4f26c2..c0903fa 100644 --- a/reagent-reitit-demo/dev.cljs.edn +++ b/reagent-reitit-demo/dev.cljs.edn @@ -5,4 +5,4 @@ :source-map true :source-map-timestamp true :devcards true - :main demo.core} + :main clojure-demo.core} diff --git a/reagent-reitit-demo/resources/public/datalog-demo.org b/reagent-reitit-demo/resources/public/datalog-demo.org index ff26487..bb1fc3c 100644 --- a/reagent-reitit-demo/resources/public/datalog-demo.org +++ b/reagent-reitit-demo/resources/public/datalog-demo.org @@ -10,6 +10,12 @@ 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. @@ -22,17 +28,17 @@ 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. +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. -*** Schema less Database -In it's simplest for we create a database connection like below. +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 "Oly" :user/img "me.jpg"} {:user/name "Sam" :user/img "you.jpg"}]) +(d/transact! demo-conn [{:user/name "Brooke" :user/img "me.jpg"} {:user/name "Kalvin" :user/img "you.jpg"}]) #+END_SRC *** Using a Schema @@ -44,18 +50,18 @@ In this example we are saying name is unique and rooms has a many to one relatio (def demo-conn (d/create-conn schema)) #+END_SRC -Transacting this data would mean Oly would be inserted once but the image will be updated to =you.jpg= +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 "Oly" :user/img "me.jpg"} {:user/name "Oly" :user/img "you.jpg"}]) + (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 =Oly= exists once so the entity db/id will be returned which can be used for further queries. +=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 @conn [:user/name "Oly"]) +(d/entity @demo-conn [:user/name "Brooke"]) #+END_SRC *** Pull a tree of data diff --git a/reagent-reitit-demo/resources/public/clojure-basics.org b/reagent-reitit-demo/resources/public/documents/clojure-basics.org similarity index 86% rename from reagent-reitit-demo/resources/public/clojure-basics.org rename to reagent-reitit-demo/resources/public/documents/clojure-basics.org index 3ece2ff..2acfe48 100644 --- a/reagent-reitit-demo/resources/public/clojure-basics.org +++ b/reagent-reitit-demo/resources/public/documents/clojure-basics.org @@ -192,19 +192,19 @@ This has some really nice side effects, one being it is very easy to navigate yo *** Basic value fetching #+BEGIN_SRC clojure :tangle src/core.cljc -(def my-hashmap {:top {:first-key 1 :second-key 2}}) +(def my-hashmap {:top-lvl-key {:first-key 1 :second-key 2}}) ;; you can get the value in a number of ways. ;; using neted get return the result of one get to the next -(get (get my-hashmap :top) :second-key) +(get (get my-hashmap :top-lvl-key) :second-key) ;; much nicer is to use get-in and specify the path -(get-in my-hashmap [:top :second-key]) +(get-in my-hashmap [:top-lvl-key :second-key]) ;; You can also call the keywords as a function -(:second-key (:top my-hashmap)) +(:second-key (:top-lvl-key my-hashmap)) ;; or using something called a threading macro -;; push the map through the :top function then the result +;; push the map through the :top-lvl-key function then the result ;; into the :second-key function -(-> my-hashmap :top :second-key) +(-> my-hashmap :top-lvl-key :second-key) #+END_SRC @@ -219,9 +219,34 @@ Using =:or= we can set default values if the key is missing, the :as keyword can * Wierd symbol's -There is a good reference on the symbols in clojure below when you encounter one your not sure about. +There is a good reference on the symbols in clojure in the link below when you encounter one your not sure about. https://clojure.org/guides/weird_characters +Below you will find some simple examples, it is worth noting that some of the wierd symbols are just shorthand for a longer function name calls. + +=:= Colon indicates a keyword's + +;; :: Double colon makes a namespaced keyword, what ever is defined at the top of your file under (ns) +;; will be pre pended to the keyword + +;; , comma is just white space and is used only for readability to the user + +;; #( is an annoymous function (fn [param1] (prn param1)) is equivalent to #(prn %) % being param1 +;; you can also use %1 %2 %3 etc to refernce other params, longer form is prefered because the params are named +;; but for very short small functions this variant can be handy + +;; -> is the threading macro, basically the result of each statement is passed to the next +;; as the first parameter, this works nicely with hashmaps because keywords are functions + +;; ->> same as above but the result is the last parameter +;; when working with sequences you tend to use this one most functions Take +;; a sequence as the last parameter + +;; '( this is the same as writting (list 1 2 3) the ' denotes we are using the list function + +;; #_ this is the comment block it + + #+BEGIN_SRC clojure :tangle src/core.cljc ;; : Colon indicates a keyword's diff --git a/reagent-reitit-demo/resources/public/documents/datalog-demo.org b/reagent-reitit-demo/resources/public/documents/datalog-demo.org new file mode 100644 index 0000000..bb1fc3c --- /dev/null +++ b/reagent-reitit-demo/resources/public/documents/datalog-demo.org @@ -0,0 +1,86 @@ +#+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. diff --git a/reagent-reitit-demo/resources/public/dsl-demo.org b/reagent-reitit-demo/resources/public/documents/dsl-demo.org similarity index 100% rename from reagent-reitit-demo/resources/public/dsl-demo.org rename to reagent-reitit-demo/resources/public/documents/dsl-demo.org diff --git a/reagent-reitit-demo/resources/public/reagent-reitit.org b/reagent-reitit-demo/resources/public/documents/reagent-reitit.org similarity index 100% rename from reagent-reitit-demo/resources/public/reagent-reitit.org rename to reagent-reitit-demo/resources/public/documents/reagent-reitit.org diff --git a/reagent-reitit-demo/resources/public/test.org b/reagent-reitit-demo/resources/public/documents/test.org similarity index 100% rename from reagent-reitit-demo/resources/public/test.org rename to reagent-reitit-demo/resources/public/documents/test.org diff --git a/reagent-reitit-demo/resources/public/index.html b/reagent-reitit-demo/resources/public/index.html new file mode 100644 index 0000000..0423534 --- /dev/null +++ b/reagent-reitit-demo/resources/public/index.html @@ -0,0 +1,98 @@ + + + +
+ + + +