Fork me on GitHub
#datomic
<
2024-04-27
>
Marlon18:04:02

Hello, Folks. I hope everyone's doing good =] Is there any way to do a get-else for a cardinality many relations? Here's a silly query just to exemplify what I want. Basically I want all the persons from a list of ids and I want their houses, and return an empty map/EntityMap if the person doesn't have any house.

(d/q '[:find ?person ?house
       :in $ [?person ...]
       :where
       [?person :person/has-doc? true]
       [(get-else $ ?house :house/persons {}) ?person] (d/db conn) ids)

Marlon00:04:10

I’ve found the previous conversations on this topic and yeah, I don’t think there’s a one fits all workaround for this. Gladly I found another solution to my problem that doesn’t involve the field I was trying to retrieve, so at least I got that haha

favila22:04:58

Not sure what conversation you’re referring to, but you can do something like this:

favila22:04:02

[:find ?person ?house
       :in $ [?person ...]
       :where
       [?person :person/has-doc? true]
       (or-join [[?person] ?house]
                (and
                 (not [_ :house/persons ?person])
                 [(ground -1) ?house])
                [?house :house/persons ?person])]

favila22:04:50

The reason get-else doesn’t work on cardinality-many or reverse-refs (amounts to the same thing--their cardinality is not constrained) is that you need some sentinel to represent “no items” which changes the number of relations.

favila22:04:14

Result set would be #{[person-id -1]} if no house, but #{[person-id house1-id] [person-id house2-id] ...} if houses.

favila22:04:07

how many houses does person-id have? You can’t determine that by counting relations

Marlon22:04:33

That's really nice, while searching I did found some people using a combination of or-join and ground to achieve this. But I couldn't make it work for me. Your solution does exactly what I was trying to do. Even tho I've found another solution that doesn't involve running this query, is nice to know a little more, thanks!