Negation

Sometimes you want to exclude results rather than include them. Datomic provides three tools for this: not, not-join, and missing?.

not

not excludes any entity for which the inner pattern matches. Variables already bound in the outer query are automatically joined. Let's find Pokemon that are not Grass type:

[:find ?name :where [?e :pokemon/name ?name] (not [?e :pokemon/type "Grass"])]

Because :pokemon/type is cardinality/many, this excludes Pokemon that have any Grass entry — so Bulbasaur (Grass/Poison) is excluded. Try changing "Grass" to "Fire" or "Water".

not-join

not-join works like not but lets you introduce fresh variables inside the negation that are only used there. You declare explicitly which outer variables to join.

Here we find single-type Pokemon — those for which there is no second, different type value:

[:find ?name ?type :where [?e :pokemon/name ?name] [?e :pokemon/type ?type] (not-join [?e ?type] [?e :pokemon/type ?other] [(not= ?type ?other)])]

For each ?name/?type pair, not-join checks whether a different type value ?other exists on the same entity. If it does, the row is dropped — leaving only single-type Pokemon.

missing?

missing? checks that an entity has no value for a given attribute. Its arguments are the database binding $, the entity variable, and the attribute keyword.

Our Pokemon database has an optional :pokemon/category attribute — only Articuno, Zapdos, Moltres, and Mewtwo have it set to true. Every other Pokemon is missing this attribute entirely. Let's find all non-legendary Pokemon:

[:find ?name :where [?e :pokemon/name ?name] [(missing? $ ?e :pokemon/category)]]

This returns all ~147 Pokemon that lack the :pokemon/category attribute. Try adding a stat like [?e :stat/hp ?hp] and including ?hp in :findmissing? only filters; the rest of the query works normally.

Try: Modify the not query at the top to exclude a different type, like "Ice" or "Dragon". Or flip the missing? demo to find legendary Pokemon by replacing missing? with a pattern clause [?e :pokemon/category :legendary].

Previous | Next