clojure-demos/reagent-reitit-demo/resources/public/documents/datalog-demo.org

3.9 KiB

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.

clojure -m figwheel.main --build dev --repl

Intro to datalog

First import datascript which is a client side version of datalog, see datomic crux datalevin and datahike for other datalog database.

#_(ns core.demo
  (:require [datascript.core :as d]))

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,

(def demo-conn (d/create-conn {}))

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.

(def demo-conn (d/create-conn {}))
(d/transact! demo-conn   [{:user/name "Brooke" :user/img "me.jpg"} {:user/name "Kalvin" :user/img "you.jpg"}])

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.

  (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))

Transacting this data would mean Brooke would be inserted once but the image will be updated to you.jpg

  (d/transact! demo-conn   [{:user/name "Brooke" :user/img "you.jpg"}])

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.

(d/entity @demo-conn [:user/name "Brooke"])

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.

(d/pull @demo-conn '[*] 1)
(d/pull @demo-conn '[:user/name :user/rooms] 1)

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.

  (d/q '[:find ?user-entity ?user-name  :where
         [?user-entity :user/name ?user-name]] @demo-conn)

Write some more as needed better examples in the src code.