Question

If I have the following Datomic database:

{ :fred :age 42 }
{ :fred :likes :pizza }
{ :sally :age 42 }

How do I query for both entities (:fred and :sally), getting back the attribute :likes :pizza for :fred and an empty value for :sally?

The query

[:find ?n ?a ?l
 :where [?n :age ?a]
        [?n :likes ?l]]

only returns :fred 42 :pizza.

Was it helpful?

Solution

Datomic has recently been updated with a few expression functions available to you in Datomic queries. One of these functions is called get-else and it lets you provide a default return value if an attribute doesn't exist on an entity, much like how clojure.core/get will return an option third param if the key isn't found.

So using your own example, you would only need to change it like so:

[:find ?n ?a ?l :where [?n :age ?a] [(get-else $ ?n :likes false) ?l]

Unfortunately you can't actually make nil a "default" value since it's not a valid Datomic data type, and Datomic will carp if you try, but false should get you where you're going as well.

OTHER TIPS

You can also try the "missing?" fn.

Have a look on this:

http://docs.datomic.com/query.html#missing

Getting back a set of entities which may or may not have particular attributes asserted is analogous to a LEFT JOIN in a relational database.

The approach in datomic is to do two steps: first query for the entities and then navigate from there to get the attribute values or nil if the attribute is not asserted for a given entity.

See the mailing list post How do you do a left join in Datomic? with its accompanying gist for an example.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top