Filtering with Predicates

In the previous chapter we matched patterns by specifying exact values like "Bulbasaur". Predicates let us filter rows using arbitrary truthy expressions.

A predicate clause is a function call wrapped in an extra pair of brackets:

"[( > ?speed 100 )]"

Every variable used in the predicate must already be bound by an earlier pattern clause. Let's find all Pokemon with a speed stat above 100:

[:find ?name ?speed :where [?e :pokemon/name ?name] [?e :stat/speed ?speed] [(> ?speed 100)]]

We can compare two bound variables against each other. Here are the Pokemon whose defense is strictly higher than their attack:

[:find ?name ?attack ?defense :where [?e :pokemon/name ?name] [?e :stat/attack ?attack] [?e :stat/defense ?defense] [(> ?defense ?attack)]]

Predicates work on strings too, this site allows clojure.string/starts-with? and clojure.string/includes?; in a real Datomic app, any Clojure function is available. Here we find Pokemon whose name starts with "S":

[:find ?name :where [?e :pokemon/name ?name] [(clojure.string/starts-with? ?name "S")]]

Or find Pokemon whose name contains "saur":

[:find ?name :where [?e :pokemon/name ?name] [(clojure.string/includes? ?name "saur")]]

Try: Combine two predicates to find Pokemon whose name starts with "S" and whose speed is above 100. Or find Pokemon whose attack and defense are both above 80.

Previous | Next