Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions resources/chapters/cardinality-many.edn
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
"But " [:code ":pokemon/type"] " is declared " [:code ":db.cardinality/many"] " in "
[:a {:href "/modeling-data"} "Modeling data"] ", "
"meaning an entity can have multiple values for the same attribute."]
[:p "In the schema this looks like:"]
[:ui/code {:db/ident :pokemon/type
:db/valueType :db.type/string
:db/cardinality :db.cardinality/many}]
[:p "The consequence for queries is important: "
"binding a cardinality/many attribute produces " [:strong "one result row per value"] ". "
"Let's see it in action. Run this query and notice how Bulbasaur appears twice:"]
Expand Down
6 changes: 3 additions & 3 deletions resources/chapters/index.edn
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"and traverse relationships between entities. You will also parameterize queries, pull whole entities back "
"as data, write reusable rules, and query the database as it looked at any point in its history. "
"Every example runs against a real database of all "
[:ui/value "pokemon" [:find (count ?e) . :where [?e :pokemon/name _]]] " original Pokémon."]
[:ui/value "pokemon" [:find (count ?e) . :where [?e :pokemon/name _]]] " original Pokemon."]

[:h2 "Who this is for"]
[:p "This guide is for anyone curious about querying with Datomic, whether or not you've used it before. "
Expand All @@ -27,7 +27,7 @@
" to visually separate parts of a query."]]
[:p "For a deeper look at Clojure's data syntax, see "
[:a {:href "https://clojure.org/reference/reader"} "the official reader reference"] "."]
[:p "No Pokémon expertise is required either. Stats, types, generations, and terms like "
[:p "No Pokemon expertise is required either. Stats, types, generations, and terms like "
"\"super-effective\" or \"legendary\" are explained as they come up, using the data itself."]

[:p "Click the \"Run\" button below to run your first Datomic Datalog query."]
Expand All @@ -40,4 +40,4 @@
"then at how a query is put together, "
"and last at how the data got into the database."]
[:ui/try-tip
[:p "Edit the query above to return Pokémon of other types like Fire or Electric."]]]}
[:p "Edit the query above to return Pokemon of other types like Fire or Electric."]]]}
15 changes: 10 additions & 5 deletions resources/chapters/negation.edn
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
:where
[?e :pokemon/name ?name]
(not [?e :pokemon/type "Grass"])]]
[:p "Because " [:code ":pokemon/type"] " is cardinality/many, this excludes Pokemon that have "
[:p "Because " [:code ":pokemon/type"] " is " [:code ":db.cardinality/many"] ", this excludes Pokemon that have "
[:em "any"] " Grass entry, so Bulbasaur (Grass/Poison) is excluded. "
"Try changing \"Grass\" to \"Fire\" or \"Water\"."]

Expand Down Expand Up @@ -48,9 +48,14 @@
[:h2 "missing?"]
[:p [:code "missing?"] " checks that an entity has no value for a given attribute. "
"Its arguments are the database binding " [:code "$"] ", the entity variable, and the attribute keyword."]
[:p "In our Pokemon database, only Articuno, Zapdos, Moltres, and Mewtwo have a "
[:code ":pokemon/category"] ", with the value " [:code ":legendary"] ". "
"In Datomic any entity can have any attribute, so for every other Pokemon that fact simply "
[:p "In our Pokemon database, only a few have a " [:code ":pokemon/category"]
", with the value " [:code ":legendary"] ":"]
[:ui/runnable "pokemon"
[:find ?name
:where
[?e :pokemon/category :legendary]
[?e :pokemon/name ?name]]]
[:p "In Datomic any entity can have any attribute, so for every other Pokemon that fact simply "
"doesn't exist: they are " [:em "missing"] " the attribute. "
"Where " [:code "get-else"] " in " [:a {:href "/function-clauses"} "Function clauses"]
" kept those Pokemon and gave them a default, " [:code "missing?"] " keeps only them. "
Expand All @@ -68,4 +73,4 @@
[:ui/try-tip
[:p "Modify the " [:code "not"] " query at the top to exclude a different type, like \"Ice\" or \"Dragon\". "
"Or flip the " [:code "missing?"] " demo to find " [:em "legendary"] " Pokemon by replacing "
[:code "missing?"] " with a pattern clause " [:code "[?e :pokemon/category :legendary]"] "."]]]}
[:code "missing?"] " with a data pattern " [:code "[?e :pokemon/category :legendary]"] "."]]]}
3 changes: 1 addition & 2 deletions resources/chapters/or-clauses.edn
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,5 @@
[:code "All clauses in 'or' must use same set of vars"] ". " [:code "?speed"] " only exists in the "
"second branch, so the two branches disagree on which variables they share; "
[:code "or-join"] " gets around this by declaring up front which ones actually are shared. "
"Add a third " [:code "or"] " branch for \"Electric\" in the first query above. "
"Or modify the " [:code "or-join"] " query to find Pokemon that are Ground-type "
"Modify the " [:code "or-join"] " query to find Pokemon that are Ground-type "
[:em "or"] " have attack above 120."]]]}
6 changes: 4 additions & 2 deletions resources/chapters/predicates.edn
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[:p "So far we matched patterns by specifying exact values like "
[:code "\"Bulbasaur\""] ". Predicates let us filter rows using arbitrary truthy expressions."]
[:p "A predicate clause is a function call wrapped in an extra pair of brackets:"]
[:ui/code "[( > ?speed 100 )]"]
[:ui/code "[(> ?speed 100)]"]
[:p "Every variable used in the predicate must be bound somewhere in the query, not necessarily by an earlier clause. "
"A variable bound nowhere is the real error:"]
[:ui/code "?nope not bound in expression clause: [(> ?nope 100)]"]
Expand All @@ -20,7 +20,9 @@
[(> ?speed 100)]]]
[:ui/try-tip
[:p "Move " [:code "[(> ?speed 100)]"] " to the top of the " [:code ":where"] " clauses, above the patterns "
"that bind " [:code "?e"] " and " [:code "?speed"] ". The query still returns the same 17 Pokemon."]]
"that bind " [:code "?e"] " and " [:code "?speed"] ". The query still returns the same "
[:ui/value "pokemon" [:find (count ?e) . :where [?e :stat/speed ?speed] [(> ?speed 100)]]]
" Pokemon."]]
[:p "We can compare two bound variables against each other. "
"Here are the Pokemon whose defense is strictly higher than their attack:"]
[:ui/runnable "pokemon"
Expand Down
6 changes: 3 additions & 3 deletions resources/chapters/querying.edn
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
:stat/speed 45}]
[:p "Each key is an " [:strong "Attribute"] " (:pokemon/name, :stat/speed, etc"
") and each value is the " [:strong "Value"] " for that attribute on this entity (Bulbasaur, 45, etc)."]
[:p "Datomic assigns every entity a unique " [:strong "entity ID"] " when it is first added. "
[:p "Datomic assigns every entity a unique " [:strong "entity id"] " when it is first added. "
"You never choose it, and because of that, code shouldn't store an entity id outside Datomic. "
"The " [:a {:href "/relationships"} "Relationships"] " chapter shows how to identify an entity a "
"different way, with a unique attribute instead. "
Expand All @@ -26,7 +26,7 @@
[:ui/runnable "pokemon"
[:find ?entity-id
:where [?entity-id :pokemon/name "Bulbasaur"]]]
[:p "Now that we have the concept of an entity ID, we can flip the query around and ask: "
[:p "Now that we have the concept of an entity id, we can flip the query around and ask: "
"what Attributes does this entity have? "
"We bind the attribute position to a logic variable, then resolve its human-readable name via "
[:code ":db/ident"] ":"]
Expand All @@ -50,7 +50,7 @@
"Attributes are themselves entities, which is why we can traverse from "
[:code "?attribute-id"] " to " [:code ":db/ident"] " to get the keyword name."]
[:p "You may notice one more attribute for Bulbasaur, " [:code ":evolution/next"] ". "
"Its value is a number: the entity ID of Ivysaur. This is a " [:strong "reference"]
"Its value is a number: the entity id of Ivysaur. This is a " [:strong "reference"]
" from one entity to another. The " [:a {:href "/relationships"} "Relationships"] " chapter shows how to "
"query references like this one, and the " [:a {:href "/pull"} "Pull"] " and " [:a {:href "/rules"} "Rules"]
" chapters follow " [:code ":evolution/next"] " itself to walk Pokemon through their evolutions."]
Expand Down
14 changes: 13 additions & 1 deletion resources/chapters/rules.edn
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,19 @@
[?e :stat/sp-defense ?sp-defense]
[?e :stat/speed ?speed]
[(+ ?hp ?attack ?defense ?sp-attack ?sp-defense ?speed) ?total]]]]
[:p "Charizard's total is 534. These are the Pokemon with a higher one."]
[:p "Charizard's total is "
[:ui/value "pokemon"
[:find ?total .
:where
[?e :pokemon/name "Charizard"]
[?e :stat/hp ?hp]
[?e :stat/attack ?attack]
[?e :stat/defense ?defense]
[?e :stat/sp-attack ?sp-attack]
[?e :stat/sp-defense ?sp-defense]
[?e :stat/speed ?speed]
[(+ ?hp ?attack ?defense ?sp-attack ?sp-defense ?speed) ?total]]]
". These are the Pokemon with a higher one."]

[:ui/try-tip
[:p "Change " [:code "\"Bulbasaur\""] " to " [:code "\"Eevee\""] " in the recursive query to see it branch. "
Expand Down
2 changes: 1 addition & 1 deletion resources/chapters/time-travel.edn
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
(as-of "Generation I")]

[:h2 "Types come and go"]
[:p "The first games had 15 types. Steel and Dark arrived in Generation II, and Fairy in Generation VI. "
[:p "The type list has grown since. Steel and Dark arrived in Generation II, and Fairy in Generation VI. "
"We recorded when each type appeared, not every later change to how types fare against each other, "
"so the type chart you see for a past generation is today's, restricted to the types that existed then. "
"How many types were there in Generation I?"]
Expand Down
Loading