81 lines
3.6 KiB
Org Mode
81 lines
3.6 KiB
Org Mode
#+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
|
|
|
|
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.
|
|
|
|
*** Schema less Database
|
|
In it's simplest for we create a database connection like below.
|
|
#+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"}])
|
|
#+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 Oly 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"}])
|
|
#+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.
|
|
#+BEGIN_SRC clojurescript :tangle ./src/test.cljc
|
|
(d/entity @conn [:user/name "Oly"])
|
|
#+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.
|