Query: all TODO blocks excluding those from today journal

Hi folks!

I’m learning the query language and I wonder how to make a query with an optional exclusion.

So I need to get all the #note blocks that have TODO marker set, but exclude those which I’m currently working on in the current day in journal.

#+BEGIN_QUERY
 {:title "🔨 TODO notes"
    :query [:find (pull ?b [*])
            :in $ ?today 
            :where
            [?b :block/marker ?marker]
            [(contains? #{"LATER" "TODO" "DOING"} ?marker)]
            [?b :block/refs ?tag]
            [?tag :block/name "note"]
            [?b :block/page ?page]
            [?page :block/journal? true]
            [?page :block/journal-day ?date]
            [(!= ?date ?today)]]
    :inputs [:today]
    :group-by-page? false
    :collapsed? false
}
#+END_QUERY

In this query I constrain :block/page to be journal. But I need to express:

if this block is in journal, then
  apply the date condition
otherwise
  ignore the date condition

How to do that?

UPD. I found a related thread: Query incomplete tasks which are not referenced from a specific page
I believe that approach is quite good: instead of checking the date, I can simply exclude blocks, that don’t belong to the current page - the journal day page.
In this case my condition changes to:

if this block belongs to the current page
  exclude it
otherwise
  include it

Try this:

(or-join [?today ?page]
    (not [?page :block/journal? true])
    (and
        [?page :block/journal? true]
        [?page :block/journal-day ?date]
        [(!= ?date ?today)]
    )
)
1 Like

I assume you just want to say:

  • Don’t show tasks that are in current journal

We can just make it a “complete” not statement.

So:

(not
  [?b :block/page ?page]
  [?page :block/journal-day ?today]
)

It basically works like this:

  • We create a subset which is #note TODO blocks that are on today’s journal page
  • Then we say, from the whole set, subtract this subset

If that makes sense?

Edit, for clarity, the complete query is:

#+BEGIN_QUERY
 {:title "🔨 TODO notes"
    :query [:find (pull ?b [*])
            :in $ ?today 
            :where
            [?b :block/marker ?marker]
            [(contains? #{"LATER" "TODO" "DOING"} ?marker)]
            [?b :block/refs ?tag]
            [?tag :block/name "note"]
            (not
              [?b :block/page ?page]
              [?page :block/journal-day ?today]
            )
    ]
    :inputs [:today]
    :group-by-page? false
    :collapsed? false
}
#+END_QUERY
2 Likes

Maybe I did something wrong, but I get an error

Insufficient bindings: none of #{?page} is bound in (not [?page :block/journal? true])

with this query:

#+BEGIN_QUERY
{:title "🔨 TODO notes (mentaloid)"
  :query [:find (pull ?b [*])
          :in $ ?today
          :where
          [?b :block/marker ?marker]
          (not [(contains? #{"DONE" "CANCELED" "CANCELLED"} ?marker)])
          [?b :block/refs ?tag]
          [?tag :block/name "note"]
          (or-join [?today ?page]
              (not [?page :block/journal? true])
              (and
                  [?page :block/journal? true]
                  [?page :block/journal-day ?date]
                  [(!= ?date ?today)]
               )
           )
  ]
  :inputs [:today]
}
#+END_QUERY

You removed this needed line:

[?b :block/page ?page]
1 Like

Thanks, it works exactly as I wished. And simple exclusion as you noticed is really what was required in this case :slight_smile:

Exactly! Thank you!

Well, that answers my question how I phrased it.
Nice to see a solution using or-join while I was thinking in SQL’s lef-joins :slight_smile:

Difficult to pick the right solution as both solve my problem.

@Siferiax I like your solution more and will use it, but will pick the mentaloid’s answer as it literally answers my question.

1 Like

:slight_smile: both are correct indeed.
My solution is more straightforward.
However, the one from mentaloid can be adapted to make a more complex query. For example the todo is not on a journal page, or on today’s journal page.
I think both have value.

2 Likes