Fork me on GitHub
#xtdb
<
2022-09-12
>
Mikko Harju10:09:30

Hi again, amateur question again – How does one handle "unify this or accept an empty result" – I have a relation that might exist (if it does – I should have a (count ?knows) – or if there are no results it should be 0 – I can do either one of those but not at the same time 😄

Mikko Harju10:09:19

I tried

(or 
  (and [?known :core/entity ?entity] 
       [?known :user/id]]) 
  [(identity nil) ?known]
)

Mikko Harju10:09:30

but that is obviously not the way to do it 🙂

Mikko Harju10:09:25

?entity is bound in the where query before that clause

Mikko Harju10:09:13

Heh, one way that I found out kind of works is [(identity true) ?known] in the other leg of that or predicate that returns N+1 matches for ones that have something and 1 for the ones that did not have anything...

Mikko Harju10:09:44

so (dec (count ?known)) gives the result I expected.

refset10:09:41

Hey, I don't have time to think about this properly right now (I'll try to circle back sometime later), but this might give some ideas: https://github.com/xtdb/xtdb/blob/065f41945daed67c6742a5c480864eaa24f6e48d/test/test/xtdb/query_test.clj#L1812

👍 1
Mikko Harju11:09:02

On the surface it looks like that or-join it returns N+1 as well if I adapt this to my query, adding the restriction to the other leg with (not [?known :user/id])

tatut11:09:10

You might want to check get-attr as well

Mikko Harju11:09:50

Thanks! It was mentioned in the docs but https://github.com/xtdb/xtdb/blob/e2f51ed99fc2716faa8ad254c0b18166c937b134/test/test/xtdb/query_test.clj#L1054 this did not open so didn't bother looking into it 😄

tatut11:09:33

user> (xt/submit-tx node [[::xt/put {:xt/id "test1" :foo 1 :have-it 42}] [::xt/put {:xt/id "test2" :foo 2}] [::xt/put {:xt/id "test3" :foo 3 :have-it 666}]])

user> (xt/q (xt/db node) '[:find ?e ?foo ?it :where [?e :foo ?foo] [(get-attr ?e :have-it) [?it]]])
#{["test3" 3 666] ["test1" 1 42] ["test2" 2 nil]}
idk if this helps in your specific query, but you can use it to “get” attributes that possibly don’t exist in the entity

Mikko Harju11:09:28

Sounds like this does not fit my current use case. I'm essentially trying to find related documents that has a link to another entity through a key. My query above "works", if it is efficient or idiomatic – that is up for debate 😄 Thanks for your input – another new shining thing in my toolbelt 🙂

refset12:09:48

> so (dec (count ?known)) gives the result I expected. If you can share the full query (that gives the expected result) we'll be able to help more easily on the "efficient or idiomatic" front

Mikko Harju12:09:36

{
            :find [?role ?group-name ?type ?name ?skill (dec (count ?knows))],
            :where [[?dept :core/role ?role]
                    [?dept :core/type ?type]
                    [?group :core/parent ?dept]
                    [?group :core/name ?group-name]
                    [?group :core/type :core/group]
                    [?skill :core/parent ?group]
                    [?skill :core/name ?name]
                    (or (and [?knows :core/skill ?skill]
                             [?knows :user/id])
                        [(identity true) ?knows])]
          }

refset20:09:28

Thanks! That doesn't seem too bad, actually, though I might change the or to an or-join to make it slightly more explicit (and potentially speed it up):

(or-join [?knows ?skill]
         (and [?knows :core/skill ?skill]
              [?knows :user/id])
         [(identity true) ?knows])

Mikko Harju04:09:01

Thank you again for your help. Changed my impl to or-join according to your suggestion 🙂

☺️ 1