Reputation: 32264
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
.
Upvotes: 11
Views: 5488
Reputation: 17181
You can also try the "missing?" fn.
Have a look on this:
http://docs.datomic.com/query.html#missing
Upvotes: 12
Reputation: 368
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.
Upvotes: 24
Reputation: 8344
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.
Upvotes: 6