Sorting by ascending "due date"

I’m trying to write an advanced query that sorts my “ongoing tasks” in ascending order of due date (earliest stuff first). I consider the due date to be the earliest of the deadline, scheduled, or journal day.

#+BEGIN_QUERY
{
:title [:h3 "Pending stuff"]
:query [
:find (pull ?block [*])
:where
[?block :block/marker ?markers]
[(contains? #{"TODO", "DOING", "WAITING"} ?markers)]
]
:result-transform (fn [result] (sort-by (fn [d]
    (min
        (get d :block/scheduled 999999999)
        (get d :block/deadline 999999999)
        (get (get d :block/page) :block/journal-day 999999999)
    )
)
result
)
)
}
#+END_QUERY

I’ve tried changing this around (e.g. the default values if the attribute can’t be found), but it’s almost as if this function isn’t even being run.

Any ideas on how I might go about implementing my intended sort function?

If you search the forum for sort-by min, you can find the proper syntax, depending on what you need (e.g. this). By the way, :block/page doesn’t return a page, but an id. EDIT: That is inside Datalog, not inside :result-transform.

1 Like

Regarding the journal page sorting aspect: I got that idea from here, and I tested it out with the following query. Am I misunderstanding something about how the (get h :block/page) works in the context of looking up the journal day? It makes sense what you say (that it just gets the id), but I’m a bit lost because this appears to keep things sorted.

#+BEGIN_QUERY
{
:title [:h2 "Sorting by due dates in journal day tasks"]
:query [
:find (pull ?block [*])
:where
; Is it a journal page?
[?block :block/page ?pageid]
[?pageid :block/journal? true]

; Is the block a task?
[?block :block/marker ?markers]
[(contains? #{"TODO", "DOING"} ?markers)]
]
:result-transform (fn [result]
(sort-by (fn [h]
(get (get h :block/page) :block/journal-day)
)
result
)
)
}
#+END_QUERY

Ignore that part, I edited my answer.

Easier way to write the same for journal-day is:
(get-in h [:block/page :block/journal-day])

@mentaloid yes, in the result set it is a nested set.

:block/page {:block/journal-day 20221119
		, :block/name "sat 19 nov 2022"
		, :block/original-name "Sat 19 Nov 2022"
		, :db/id 19}

Lol old example is old. So the double get or the get-in gets a specific key within a specific key. And gives the value of that key.

PS. For performance I would swap the statements.
Is the block a task? first and then Is it a journal page?
(Or rather is it on a journal page)
Difference is that now you get all the block in the graph first, then narrow it down. The other way around you first only get all tasks and then narrow it down further.
The more blocks your graph has the slower the query becomes. Whereas the number of specific tasks blocks would likely always be lower than the total number of blocks. Especially open tasks.