Fork me on GitHub
#datomic
<
2020-09-20
>
João Fernandes09:09:26

Hi, I've been trying do find a way to do a left join for last three days and I finally decided to ask for help 😅 How can I get all owners and their pets even if they don't currently have a pet?

[:find ?owner-name ?pet-name
 :where [?owner :owner/name ?owner-name]
        [?owner :owner/pets ?pet]
        [?pet :pet/name ?pet-name]]

João Fernandes09:09:26

Hi, I've been trying do find a way to do a left join for last three days and I finally decided to ask for help 😅 How can I get all owners and their pets even if they don't currently have a pet?

[:find ?owner-name ?pet-name
 :where [?owner :owner/name ?owner-name]
        [?owner :owner/pets ?pet]
        [?pet :pet/name ?pet-name]]

Giovani Altelino14:09:12

You could to use an or-join

Giovani Altelino14:09:59

[:find ?owner-name ?pet-name
 :with ?data-point
 :where [?owner :owner/name ?owner-name]
        [?owner :owner/pets ?pet]
        [?pet :pet/name ?pet-name]
 (or-join [?owner-name ?pet-name ?data-point]
   (and [(identity? ?owner-name) ?data-point)
   (and [(identity? ?pet-name) ?data-point)]

Giovani Altelino14:09:37

I guess something like this should work, although I don't have datomic installed right now to confirm

David Pham09:09:28

find all owners and pull the results?

João Fernandes09:09:11

Is there a way to do it in "one trip" or am I making a conceptual mistake here?

pithyless09:09:25

@joaovitorfernandes2 as a rule of thumb, I suggest using where clauses for filtering and pull for pulling data (that may or may not exist)

[:find (pull ?owner [:owner/name {:owner/pets [:pet/name]}])
 :where [?owner :owner/name _]]
So, you could use get-else in the where clause to optionally find pets, but that only makes sense if you then want to filter with additional rules (e.g. if the owner has a pet, one of the pets names need to be "Rex")

pithyless09:09:37

When you want conditional matching, you need to add a datalog rule (or one of the sugar syntaxes - e.g. or)

João Fernandes10:09:57

Thank you so much! Yesterday I tried to use pull but I didn't knew I could nest maps in there! Again, thank you!

pithyless13:09:20

@joaovitorfernandes2 Technically, that is not a nested map, but the notation for doing a join. I recommend checking out the pull docs for the kinds of built-in features you can take advantage of: https://docs.datomic.com/on-prem/pull.html The syntax has been re-used in other libraries (e.g. it is the basis for https://github.com/edn-query-language/eql and used by libraries such as Fulcro and Pathom, among others)

schmee09:09:25

@joaovitorfernandes2 I think you can use get-else for this: https://docs.datomic.com/cloud/query/query-data-reference.html#get-else

João Fernandes09:09:20

The union happens on [?owner :owner/pets ?pet] and get-else doesn't support cardinality-many attributes 😣

bhurlow20:09:39

I'm seeing some memcached/item-too-large logs when integrating memcached (same with valcache), could I be missing some required config?

favila21:09:14

You have segments which are too large to cache. This is not configurable. Probably you have some large string or binary values

bhurlow02:09:54

thanks, that could make sense

bhurlow02:09:04

I believe I have a few run away string values

bhurlow02:09:23

does retraction affect the storage of large strings in the segments or do those stay for good?

cmdrdats11:09:15

You could excise the values? That should get rid of them

bhurlow14:09:32

I'm going to try excising, though I remember reading that it's not made to reduce the size of stored data necessarily

favila14:09:45

It’s not, but if you have a too-large value that’s the only way to ensure it’s not written to segments again

favila14:09:31

It’s actually OK to have item-too-large occasionally. All this means is that the item will be fetched from storage instead of memcache/valcache

favila14:09:38

it will still be kept in object cache

favila14:09:56

that said, there’s a reason they say to keep strings under 4k

bhurlow15:09:16

thanks. In this case the data size was by accident