Get Logical with Datalog
Stuart Halloway
Datomic Team, Clojure/core, Relevance
1
Get Logical with Datalog Stuart Halloway Datomic Team, - - PowerPoint PPT Presentation
Get Logical with Datalog Stuart Halloway Datomic Team, Clojure/core, Relevance 1 https://github.com/clojure/core.logic https://github.com/nathanmarz/cascalog http://datomic.com/ 2 Roadmap How Why Bonus Round problem /
Stuart Halloway
Datomic Team, Clojure/core, Relevance
1
2
3
4
5
6
7
8
9
10
11
12
13
entity attribute value 42 :email jdoe@example.com 43 :email jane@example.com 42 :orders 107 42 :orders 141
14
[?customer :email ?email]
15
[?customer :email ?email]
entity attribute value
16
[?customer :email ?email]
constant
17
[?customer :email ?email]
variable variable
18
entity attribute value 42 :email jdoe@example.com 43 :email jane@example.com 42 :orders 107 42 :orders 141
19
20
entity attribute value 42 :email jdoe@example.com 43 :email jane@example.com 42 :orders 107 42 :orders 141
21
22
entity attribute value 42 :email jdoe@example.com 43 :email jane@example.com 42 :orders 107 42 :orders 141
23
24
entity attribute value 42 :email jdoe@example.com 43 :email jane@example.com 42 :orders 107 42 :orders 141
25
data pattern
26
variable to return
27
28
import static datomic.Peer.q; q("[:find ?customer :where [?customer :id] [?customer :orders]]", db);
29
import static datomic.Peer.q; q("[:find ?customer :where [?customer :id] [?customer :orders]]", db);
30
import static datomic.Peer.q; q("[:find ?customer :where [?customer :id] [?customer :orders]]", db);
31
import static datomic.Peer.q; q("[:find ?customer :where [?customer :id] [?customer :orders]]", db);
32
33
q([:find ?customer :in $database ?email :where [$database ?customer :email ?email]], db, "jdoe@example.com");
34
q([:find ?customer :in $database ?email :where [$database ?customer :email ?email]], db, "jdoe@example.com");
35
q([:find ?customer :in $database ?email :where [$database ?customer :email ?email]], db, "jdoe@example.com");
36
q([:find ?customer :in $database ?email :where [$database ?customer :email ?email]], db, "jdoe@example.com");
37
q([:find ?customer :in $ ?email :where [$ ?customer :email ?email]], db, "jdoe@example.com");
38
q([:find ?customer :in $ ?email :where [ ?customer :email ?email]], db, "jdoe@example.com"); no need to specify $
39
40
[:find ?item :where [?item :item/price ?price] [(< 50 ?price)]]
41
42
bound inputs
43
bind return values
44
[:find ?customer ?product :where [?customer :shipAddress ?addr] [?addr :zip ?zip] [?product :product/weight ?weight] [?product :product/price ?price] [(Shipping/estimate ?zip ?weight) ?shipCost] [(<= ?price ?shipCost)]]
45
[:find ?customer ?product :where [?customer :shipAddress ?addr] [?addr :zip ?zip] [?product :product/weight ?weight] [?product :product/price ?price] [(Shipping/estimate ?zip ?weight) ?shipCost] [(<= ?price ?shipCost)]]
navigate from customer to zip
46
[:find ?customer ?product :where [?customer :shipAddress ?addr] [?addr :zip ?zip] [?product :product/weight ?weight] [?product :product/price ?price] [(Shipping/estimate ?zip ?weight) ?shipCost] [(<= ?price ?shipCost)]]
get product facts needed during query
47
[:find ?customer ?product :where [?customer :shipAddress ?addr] [?addr :zip ?zip] [?product :product/weight ?weight] [?product :product/price ?price] [(Shipping/estimate ?zip ?weight) ?shipCost] [(<= ?price ?shipCost)]]
call web service to bind shipCost
48
public class Shipping { public static BigDecimal estimate(String zip1, int pounds); }
49
[:find ?customer ?product :where [?customer :shipAddress ?addr] [?addr :zip ?zip] [?product :product/weight ?weight] [?product :product/price ?price] [(Shipping/estimate ?zip ?weight) ?shipCost] [(<= ?price ?shipCost)]]
constrain price
50
[:find ?customer ?product :where [?customer :shipAddress ?addr] [?addr :zip ?zip] [?product :product/weight ?weight] [?product :product/price ?price] [(Shipping/estimate ?zip ?weight) ?shipCost] [(<= ?price ?shipCost)]]
return customer, product pairs
51
52
53
54
55
56
purpose assessment make an arbitrary choice
default the common choice
automate boilerplate dangerous
57
[?person :club ?club]
58
59
[?person ?attr ?value]
attribute slot isn’t special
60
[?e :db/valueType]
find all attributes
61
SELECT ID FROM CUSTOMERS;
in what db?
62
q("[:find ?customer :where [?customer :id] [?customer :orders]]", db);
in this db!
63
q([:find ?customer :in $database ?email :where [$database ?customer :email ?email]], db, "jdoe@example.com");
parameterized query is not a separate feature
64
(q '[:find ?k :in [[?k]]] (System/getProperties))
65
(q '[:find ?k :in [[?k]]] (System/getProperties))
bind first element of each tuple in a relation
66
Pattern Binds Example Input Binds ?a To ?a scalar 42 42 [?a ?b] tuple [1 2] 1 [?a ...] collection [1 2] 1, 2 [[?a ?b ?c]] relation
john likes pizza jane likes pasta
john, jane
67
(q '[:find ?v :in [[?k ?v]] :where [(.endsWith ?k "path")]] (System/getProperties))
68
(q '[:find ?pathElem :in [[?k ?v]] :where [(.endsWith ?k "path")] [(.split ?v ":") [?pathElem ...]]] (System/getProperties))
69
(q '[:find ?pathElem :in [[?k ?v]] :where [(.endsWith ?k "path")] [(.split ?v ":") [?pathElem ...]] [(.endsWith ?pathElem ".jar")]] (System/getProperties))
70
q("[:find ?customer :where [?customer :id] [?customer :orders]]", db.asOf(lastMonth));
71
[:find ?customer ?email :in $cust $emp :where [$cust ?customer :email ?email] [$emp _ :email ?email]]
q(query, custDb, empDb);
implicit join
72
[:find ?customer ?email :in $cust $emp :where [$cust ?customer :email ?email] [$emp _ :email ?email]]
q(query, custDb, empDb);
data patterns can be led by database names
73
choices
74
[(relatedProduct ?p1 ?p2) [?p1 :category ?c] [?p2 :category ?c] [(!= ?p1 ?p2)]]
75
[(relatedProduct ?p1 ?p2) [?p1 :category ?c] [?p2 :category ?c] [(!= ?p1 ?p2)]]
this is true...
76
[(relatedProduct ?p1 ?p2) [?p1 :category ?c] [?p2 :category ?c] [(!= ?p1 ?p2)]]
...if all these are true
77
q("[:find ?p2 :in $ % :where (expensiveChocolate p1) (relatedProduct p1 p2)", db, rules)
rules are a kind of input
78
q("[:find ?p2 :in $ % :where (expensiveChocolate p1) (relatedProduct p1 p2)", db, rules)
rule names begin with %
79
q("[:find ?p2 :in $ % :where (expensiveChocolate p1) (relatedProduct p1 p2)", db, rules)
rule patterns can appear in :where clause
80
[[(relatedProduct ?p1 ?p2) [?p1 :category ?c] [?p2 :category ?c] [(!= ?p1 ?p2)]] [(relatedProduct ?p1 ?p2) [?o :order/item ?item1] [?item1 :order/product ?p1] [?o :order/item ?item2] [?item2 :order/product ?p2] [(!= ?p1 ?p2)]]]
81
Line Item 1 Order Line Item 2 Product A Product B Customer
82
Line Item 1 Order Line Item 2 Product A Product B Customer
83
[(extent ?x ?e ?a ?v) (?e ?a ?v) (?x ?a ?v) [(= ?e ?x)]]
Line Item 1 Order Line Item 2 Product A Product B Customer
84
[(extent ?x ?e ?a ?v) (?e ?a ?v) (?e ?a ?x) [(= ?v ?x)]]
Line Item 1 Order Line Item 2 Product A Product B Customer
matches ref from customer, not customer itself
85
[(extent ?x ?e ?a ?v) (components ?x ?y) (extent ?y ?e ?a ?v)] [(components ?p ?c) (?a :db/isComponent) (?p ?a ?c)]
Line Item 1 Order Line Item 2 Product A Product B Customer
86
[(extent ?x ?e ?a ?v) (components ?x ?y) (extent ?y ?e ?a ?v)] [(components ?p ?c) (?a :db/isComponent) (?p ?a ?c)]
Line Item 1 Order Line Item 2 Product A Product B Customer
recursive definition
87
[(extent ?x ?e ?a ?v) (components ?x ?y) (extent ?y ?e ?a ?v)] [(components ?p ?c) (?a :db/isComponent) (?p ?a ?c)]
Line Item 1 Order Line Item 2 Product A Product B Customer
marked :db/isComponent
88
89