Datomic logical disjunction

244 views Asked by At

I'm sorry if this is painfully obvious, but how do I represent logical disjunction in Datomic? For instance, if I'm looking for an entity whose name is "1" or whose age is less than 5, how would I go about that?

Thanks!

2

There are 2 answers

0
Ben Kamphaus On

You can accomplish this by using rules. An example from the docs shows a rule form that expresses logical OR:

[[(social-media ?c)
  [?c :community/type :community.type/twitter]]
 [(social-media ?c)
  [?c :community/type :community.type/facebook-page]]]

In this case, the rule defines two logical paths to meet the definition "social-media." So, either community/type twitter or community/type facebook-page meet the criteria for "social media." This example is fleshed out in more detail towards the end of the "querying with rules" section of the tutorial.

(let [rules '[[[region ?c ?r]
               [?c :community/neighborhood ?n]
               [?n :neighborhood/district ?d]
               [?d :district/region ?re]
               [?re :db/ident ?r]]
              [[social-media ?c]
               [?c :community/type :community.type/twitter]]
              [[social-media ?c]
               [?c :community/type :community.type/facebook-page]]
              [[northern ?c]
               (region ?c :region/ne)]
              [[northern ?c]
               (region ?c :region/n)]
              [[northern ?c]
               (region ?c :region/nw)]
              [[southern ?c]
               (region ?c :region/sw)]
              [[southern ?c]
               (region ?c :region/s)]
              [[southern ?c]
               (region ?c :region/se)]]]
  (pprint (q '[:find [?n ...]
               :in $ %
               :where
               [?c :community/name ?n]
               (southern ?c)
               (social-media ?c)]
             (db conn)
             rules)))

This example combines multiple logical pathways to inclusion in southern - :region/sw, region:se, and region:s, as well as multiple pathways into social media.

0
dhaffey On

As of 0.9.5130, you can write disjunctive queries directly:

(q '[:find ?e
     :where
     (or-join [?e]
       [?e :name "1"]
       (and [?e :age ?age]
            [(< ?age 5)]))]
   db)

For a quick overview of the new functionality, check out the blog post where they announced it.