Fork me on GitHub
#xtdb
<
2021-01-17
>
Christopher Thonfeld-Guckes13:01:26

Hey guys, I'm struggling with a query. I have a few entities like this

{:uuid ... :type :doc :version 7}
and I want to query all entities of :type doc with a :version lower than e.g. 18. I've seen the documentation on using predicates but that only covers input data. The first part of my query looks like this:
{:find  [document]
 :in    [version]
 :where [[document :type :doc]
         [... what goes here? (> )...]]}
Many thanks in advance

3
Christopher Thonfeld-Guckes13:01:09

I found the solution in the datomic documentation:

{:find  [document db-version]
 :in    [version]
 :where [[document :type :doc]
         [document :version db-version]
         [(< db-version version)]]}
The documentation would probably benefit from a few more examples that go beyond "This field is exactly this value". I'd be happy to write some prose if you guys could provide me with some example queries.

Christopher Thonfeld-Guckes14:01:21

Another problem though: This query doesn't return any entities with the :version entry missing. I tried to achieve this with a not-join on the version I do want but this doesn't seem to work properly:

(crux/q (crux/db db)
                       '{:find  [document]
                         :in    [db-version]
                         :where [[document :type :document]
                                 (not-join
                                   [document]
                                   [document :version version])
                                 ]}
                       1)
This returns only the items with :version = 1 which looks like a bug to me. With a fixed version number, it works perfectly:
(crux/q (crux/db db)
                       '{:find  [document]
                         :in    [db-version]
                         :where [[document :type :doc]
                                 (not-join
                                   [document]
                                   [document :version 1])
                                 ]}
                       version)
returns all items that don't have the :version flag or a different :version than 1. @U899JBRPF, can you tell me, what I'm doing wrong?

Toyam Cox20:01:16

Sounds like you want two queries, one where you check for the version being there, and another where it is absent

Toyam Cox20:01:39

Alternately a migration step where you take all documents without a version tag and tag them version -1 or something

Toyam Cox20:01:38

Or perhaps 2 sets of arguments, one where you give the document version, another where you give nil for not-there

Christopher Thonfeld-Guckes13:01:12

I tried giving nil but it seems, the database doesn't return items that don't have the given key. I managed to get it to work using the following query:

'{:find  [document db-version]
  :in    [version]
  :where [[document :db-type :document]
          [(get-attr document :version nil) [db-version ...]]
          [(not= db-version version)]]}

refset12:01:54

(hey, sorry to chime in late 😅 ) ^that's a pretty reasonable solution. You could also use an or rule but it would be less concise. > This returns only the items with :version = 1 which looks like a bug to me. I'm surprised about this also, based on what you pasted. I would have expected it to only return docs without any version value. If you are able to share a more complete repro I would gladly dig in.