Querying Basics
The query on the first page matched facts stored in our Pokemon database. Let's look at how those facts appear, and query them.
Each Pokemon is stored as an Entity. Here is what Bulbasaur looks like:
Each key is an Attribute (:pokemon/name, :stat/speed, etc) and each value is the Value for that attribute on this entity (Bulbasaur, 45, etc).
Datomic assigns every entity a unique 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 Relationships chapter shows how to identify an entity a different way, with a unique attribute instead. (See the Datomic data model.) Let's find Bulbasaur's:
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 :db/ident:
The underscore _ in the third position is a wildcard, it matches any value but does not bind it to a variable.
Finally, we can pull all attribute-value pairs at once by binding the value position too:
This works because of Datomic's Universal Schema. Every fact in the database is stored following this Entity-Attribute-Value structure. Attributes are themselves entities, which is why we can traverse from ?attribute-id to :db/ident to get the keyword name.
You may notice one more attribute for Bulbasaur, :evolution/next. Its value is a number: the entity id of Ivysaur. This is a reference from one entity to another. The Relationships chapter shows how to query references like this one, and the Pull and Rules chapters follow :evolution/next itself to walk Pokemon through their evolutions.
Try changing "Bulbasaur" to another Pokemon name in the queries above.
Take a look at the EDN file defining all of the Pokemon in our database. It is written as one transaction for each game generation, which the Time travel chapter explains.
Run the last query with a dual-typed Pokemon like "Charizard" and observe how many attribute-value rows appear: one for each fact stored about that entity.
- Read a Pokemon's stored facts as entity/attribute/value triples.
- Find an entity's id, then use it to list its own attributes and values.
- Explain why the same query shape works on any entity, thanks to Datomic's universal schema.