Advanced Query for NOW or due today/overdue

What about this one?

#+BEGIN_QUERY
{ :query [:find (pull ?b [*])
  :in $ ?today ?tomorrow
  :where
    [?b :block/marker ?m]
    [(get-else $ ?b :block/scheduled ?tomorrow) ?d]
    (or 
      [(= "NOW" ?m)]
      [(<= ?d ?today)])]
:inputs [:today :1d-after]
:result-transform (fn [result]
  (sort-by (fn [h]
    (get-in h [:block/scheduled])) result))
:breadcrumb-show? false}
#+END_QUERY

What went wrong in your try:

You defined ?d in the same and that you wanted to use it in. I guess, that the clauses inside the and are separated (their variables are only unified after both are evaluated).

What happens in my possible solution

the get-else function takes

  1. a database ($)
  2. an entity identifier (?b)
  3. an attribute (:block/scheduled)
  4. a default value (?tomorrow)

and returns the entities attribute-value, or the default value, if it fails.
So [(get-else $ ?b :block/scheduled ?tomorrow) ?d] unifies ?d with either the scheduled date, or if there is none, with ?tomorrow.

Afterwards we can obviously check for either marker being “NOW” or schedule date being at most ?today (which, in particular, ?tomorrow is not).

For further reference you can also check Datomic Queries and Rules | Datomic (the whole page)

To improve

I only used the tomorrow’s date as a default value, because it’s bigger than today’s (that way stuff that isn’t a “NOW” and is not scheduled, gets a value that makes the or-evaluation false).
Maybe it would be better to use some “Maximum date” value, but I don’t know whether that exists.

2 Likes