Created
August 27, 2013 06:21
-
-
Save klang/6350215 to your computer and use it in GitHub Desktop.
Learn datolog today
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; http://www.learndatalogtoday.org/ | |
;; Find movie titles made in 1985 | |
[:find ?title | |
:where | |
[?m :movie/year 1985] | |
[?m :movie/title ?title]] | |
;; What year was "Alien" released? | |
[:find ?year | |
:where | |
[?e :movie/title "Alien"] | |
[?e :movie/year ?year]] | |
;; Who directed RoboCop? | |
;; You will need to use [<movie-eid> :movie/director <person-eid>] | |
;; to find the director for a movie. | |
[:find ?name | |
:where | |
[?m :movie/title "RoboCop"] | |
[?m :movie/director ?d] | |
[?d :person/name ?name]] | |
;; Find directors who has directed Arnold Schwarzenegger in a movie. | |
[:find ?name | |
:where | |
[?m :movie/cast ?c] | |
[?c :person/name "Arnold Schwarzenegger"] | |
[?m :movie/director ?d] | |
[?d :person/name ?name]] | |
;; Parameterized queries | |
;; Find movie title by year | |
1988 | |
[:find ?title | |
:in $ ?year | |
:where | |
[?e :movie/title ?title] | |
[?e :movie/year ?year]] | |
;; Given a list of movie titles, find the title and the year that movie was released. | |
["Lethal Weapon" "Lethal Weapon 2" "Lethal Weapon 3"] | |
[:find ?title ?year | |
:in $ [?title ...] | |
:where | |
[?m :movie/year ?year] | |
[?m :movie/title ?title]] | |
;; Write a query that, given an actor name and a relation with movie-title/rating, finds the movie titles and corresponding rating for which that actor was a cast member. | |
"Mel Gibson" | |
[["Die Hard" 8.3] | |
["Alien" 8.5] | |
["Lethal Weapon" 7.6] | |
["Commando" 6.5] | |
["Mad Max Beyond Thunderdome" 6.1] | |
["Mad Max 2" 7.6] | |
["Rambo: First Blood Part II" 6.2] | |
["Braveheart" 8.4] | |
["Terminator 2: Judgment Day" 8.6] | |
["Predator 2" 6.1] | |
["First Blood" 7.6] | |
["Aliens" 8.5] | |
["Terminator 3: Rise of the Machines" 6.4] | |
["Rambo III" 5.4] | |
["Mad Max" 7.0] | |
["The Terminator" 8.1] | |
["Lethal Weapon 2" 7.1] | |
["Predator" 7.8] | |
["Lethal Weapon 3" 6.6] | |
["RoboCop" 7.5]] | |
[:find ?title ?rating | |
:in $ ?cast [[?title ?rating]] | |
:where | |
[?m :movie/title ?title] | |
[?m :movie/cast ?c] | |
[?c :person/name ?cast]] | |
;; More queries | |
;; What attributes are associated with a given movie. | |
[:find ?attr | |
:in $ ?title | |
:where | |
[?m :movie/title ?title] | |
[?m ?a] | |
[?a :db/ident ?attr]] | |
;; Find the names of all people associated with a particular movie | |
;; (i.e. both the actors and the directors) | |
"Die Hard" | |
[:movie/cast :movie/director] | |
[:find ?name | |
:in $ ?title [?attr ...] | |
:where | |
[?m :movie/title ?title] | |
[?m ?attr ?p] | |
[?p :person/name ?name]] | |
;; Find all available attributes, their type and their cardinality. This is essentially a query to find the schema of the database. To find all installed attributes you must use the :db.install/attribute attribute. You will also need to use the :db/valueType and :db/cardinality attributes as well as :db/ident. | |
[:find ?attr ?type ?card | |
:where | |
[?e :db.install/attribute ?a] | |
[?a :db/ident ?attr] | |
[?a :db/valueType ?t] | |
[?t :db/ident ?type] | |
[?a :db/cardinality ?c] | |
[?c :db/ident ?card]] | |
;; When was the seed data imported into the database? Grab the transaction of any datom in the database, e.g., [_ :movie/title _ ?tx] and work from there. | |
[:find ?inst | |
:where | |
[_ :movie/title _ ?tx] | |
[?tx :db/txInstant ?inst]] | |
;; Find movies older than a certain year (inclusive) | |
[:find ?title | |
:in $ ?limit-year | |
:where | |
[?e :movie/title ?title] | |
[?e :movie/year ?year] | |
[(<= ?year ?limit-year)]] | |
;; Find movies newer than ?year (inclusive) and has a ?rating higher than the one supplied | |
1990 | |
8.0 | |
[["Die Hard" 8.3] | |
["Alien" 8.5] | |
["Lethal Weapon" 7.6] | |
["Commando" 6.5] | |
["Mad Max Beyond Thunderdome" 6.1] | |
["Mad Max 2" 7.6] | |
["Rambo: First Blood Part II" 6.2] | |
["Braveheart" 8.4] | |
["Terminator 2: Judgment Day" 8.6] | |
["Predator 2" 6.1] | |
["First Blood" 7.6] | |
["Aliens" 8.5] | |
["Terminator 3: Rise of the Machines" 6.4] | |
["Rambo III" 5.4] | |
["Mad Max" 7.0] | |
["The Terminator" 8.1] | |
["Lethal Weapon 2" 7.1] | |
["Predator" 7.8] | |
["Lethal Weapon 3" 6.6] | |
["RoboCop" 7.5]] | |
[:find ?title | |
:in $ ?year ?rate [[?title ?rating]] | |
:where | |
[?e :movie/title ?title] | |
[?e :movie/year ?y] | |
[(<= ?year ?y)] | |
[(< ?rate ?rating)]] | |
;; Transformation functions | |
;; Find people by age. Use the function tutorial.fns/age to find the age given a birthday and a date representing "today". | |
63 | |
#inst "2013-08-02T00:00:00.000-00:00" | |
[:find ?name | |
:in $ ?age ?today | |
:where | |
[?p :person/name ?name] | |
[?p :person/born ?born] | |
[(tutorial.fns/age ?born ?today) ?age]] | |
;; Find people younger than Bruce Willis and their ages. | |
#inst "2013-08-02T00:00:00.000-00:00" | |
[:find ?name ?age | |
:in $ ?today | |
:where | |
[?p :person/name ?name] | |
[?p :person/born ?born] | |
[?b :person/name "Bruce Willis"] | |
[?b :person/born ?bborn] | |
[(tutorial.fns/age ?bborn ?today) ?bage] | |
[(tutorial.fns/age ?born ?today) ?age] | |
[(< ?age ?bage)]] | |
;; ah, comparing the dates directly is legal. No need to calculate the age. | |
[:find ?name ?age | |
:in $ ?today | |
:where | |
[?p :person/name "Bruce Willis"] | |
[?p :person/born ?sborn] | |
[?p2 :person/name ?name] | |
[?p2 :person/born ?born] | |
[(< ?sborn ?born)] | |
[(tutorial.fns/age ?born ?today) ?age]] | |
;; The birthday paradox states that in a room of 23 people there is a 50% chance that someone has the same birthday. Write a query to find who has the same birthday. Use the < predicate on the names to avoid duplicate answers. You can use (the deprecated) .getDate and .getMonth java Date methods. | |
[:find ?name-1 ?name-2 | |
:where | |
[?p1 :person/name ?name-1] | |
[?p1 :person/born ?born-1] | |
[?p2 :person/name ?name-2] | |
[?p2 :person/born ?born-2] | |
[(.getDate ?born-1) ?d1 ] | |
[(.getDate ?born-2) ?d2 ] | |
[(.getMonth ?born-1) ?m1 ] | |
[(.getMonth ?born-2) ?m2 ] | |
[(= ?d1 ?d2)] | |
[(= ?m1 ?m2)] | |
[(< ?name-1 ?name-2)]] | |
;; using duplicate versions of ?m and ?d elliminate the need to compare them.. nifty! | |
[:find ?name-1 ?name-2 | |
:where | |
[?p1 :person/name ?name-1] | |
[?p2 :person/name ?name-2] | |
[?p1 :person/born ?born-1] | |
[?p2 :person/born ?born-2] | |
[(.getMonth ?born-1) ?m] | |
[(.getMonth ?born-2) ?m] | |
[(.getDate ?born-1) ?d] | |
[(.getDate ?born-2) ?d] | |
[(< ?name-1 ?name-2)]] | |
;; Aggregates | |
;; count the number of movies in the database | |
[:find (count ?e) | |
:where | |
[?e :movie/title]] | |
;; Find the birth date of the oldest person in the database. | |
[:find (min ?date) | |
:where | |
[?e :person/born ?date]] | |
;;Given a collection of actors and (the now familiar) ratings data. Find the avarage rating for each actor. The query should return the actor name and the avg rating. | |
["Sylvester Stallone" "Arnold Schwarzenegger" "Mel Gibson"] | |
[["Die Hard" 8.3] | |
["Alien" 8.5] | |
["Lethal Weapon" 7.6] | |
["Commando" 6.5] | |
["Mad Max Beyond Thunderdome" 6.1] | |
["Mad Max 2" 7.6] | |
["Rambo: First Blood Part II" 6.2] | |
["Braveheart" 8.4] | |
["Terminator 2: Judgment Day" 8.6] | |
["Predator 2" 6.1] | |
["First Blood" 7.6] | |
["Aliens" 8.5] | |
["Terminator 3: Rise of the Machines" 6.4] | |
["Rambo III" 5.4] | |
["Mad Max" 7.0] | |
["The Terminator" 8.1] | |
["Lethal Weapon 2" 7.1] | |
["Predator" 7.8] | |
["Lethal Weapon 3" 6.6] | |
["RoboCop" 7.5]] | |
[:find ?cast (avg ?rating) | |
:in $ [?cast ...] [[?title ?rating]] | |
:where | |
[?m :movie/title ?title] | |
[?m :movie/cast ?c] | |
[?c :person/name ?cast]] | |
;; Rules | |
;; Write a rule [movie-year ?title ?year] where ?title is the title of some movie and ?year is that movies release year. | |
[:find ?title | |
:in $ % | |
:where | |
(movie-year ?title 1991)] | |
[[(movie-year ?title ?year) | |
[?m :movie/year ?year] | |
[?m :movie/title ?title]]] | |
;; Two people are friends if they have worked together in a movie. Write a rule [friends ?p1 ?p2] where p1 and p2 are person entities. Try with a few different ?name inputs to make sure you got it right. There might be some edge cases here. | |
[:find ?friend | |
:in $ % ?name | |
:where | |
[?p1 :person/name ?name] | |
(friends ?p1 ?p2) | |
[?p2 :person/name ?friend]] | |
[[(friends ?p1 ?p2) | |
[?m :movie/director ?p1] | |
[?m :movie/cast ?p2]]] | |
"James Cameron" | |
;; ah, there is a difference between the cast and director .. | |
;; and "worked together" applies across that difference | |
;; "I give up" | |
[[(friends ?p1 ?p2) [?m :movie/cast ?p1] [?m :movie/cast ?p2]] | |
[(friends ?p1 ?p2) [?m :movie/cast ?p1] [?m :movie/director ?p2]] | |
[(friends ?p1 ?p2) (friends ?p2 ?p1)]] | |
;;Write a rule [sequels ?m1 ?m2] where ?m1 and ?m2 are movie entities. You'll need to use the attribute :movie/sequel. To implement this rule correctly you can think of the problem like this: A movie ?m2 is a sequel of ?m1 if either | |
;; ?m2 is the "direct" sequel of m1 or | |
;; ?m2 is the sequel of some movie ?m and that movie ?m is the sequel to ?m1. | |
;; There are (at least) three different ways to write the above query. Try to find all three solutions. | |
[:find ?sequel | |
:in $ % ?title | |
:where | |
[?m :movie/title ?title] | |
(sequels ?m ?s) | |
[?s :movie/title ?sequel]] | |
[[(sequels ?m1 ?m2) ...]] | |
"Mad Max" | |
[[(sequels ?m1 ?m2) [?m1 :movie/sequel ?m2]] | |
[(sequels ?m1 ?m2) [?m1 :movie/sequel ?m] [?m :movie/sequel ?m2]]] | |
;; "I give up" | |
[[(sequels ?m1 ?m2) [?m1 :movie/sequel ?m2]] | |
[(sequels ?m1 ?m2) [?m :movie/sequel ?m2] (sequels ?m1 ?m)]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment