How to exclude blocks that are templates or child (nested too) of templates from a query?

Hi,
I’m using templates as a way to insert checklists in my notes, to drive a workflow.
Unfortunately, my custom query for TODO items include these templates (that have checkboxes) but for obvious reasons I don’t want the checkboxes to be “checked”.

Is there any way I can exclude templates?

{ :title "⭐️ Focus"
    :query [:find (pull ?b [*])
      :in $ ?today ?tomorrow
      :where
        [?b :block/marker ?m]
            (not [(contains? #{"DONE" "CANCELED"} ?m)])
        [(get-else $ ?b :block/scheduled ?tomorrow) ?d]
        (or
          [(contains? #{"NOW" "DOING"} ?m)]
          [(<= ?d ?today)])]
    ;;:inputs [:today :1d-after]
    :inputs [:today 99990101]
    :breadcrumb-show? true
    :collapsed? false}
1 Like

@francescob did you ever find a solution?

This sounds doable. Could you provide some example blocks and templates?

I resorted to adding a tag to the template and excluding it. I don’t love it, but it allowed me to use the simple syntax

1 Like

I have a template (in org-mode format) called “Plan my day” where I have a sequence of TODOs that I go through in order to get up and running, e.g.

* Plan my day
:PROPERTIES:
:template: Plan my day
:END:
** TODO Start *Pomodoro* timer
** TODO Turn on *focus music*
** TODO Put desk in *standing* mode and turn *walking pad* on
** TODO Connect devices to *charge*
* ...

Now I would like to create a table on the [[TODO]] page where I list all TODOs sorted by priority, but of course excluding those from my templates.

I have the sorting and everything working, the simplified query looks something like this:

#+BEGIN_QUERY
{ :title "TODOs"
  :query [:find (pull ?b [*])
        :in $ ?current-page
        :where
        [?b :block/marker ?marker]
        [?b :block/page ?p]
        [(contains? #{"TODO" "WAIT" "LATER"} ?marker)]
    ]
:inputs
    [:current-page]
  :result-transform (fn [result]
                                 (sort-by (fn [h]
                                                  (get h :block/priority "Z")) (map (fn [r] (assoc r :block/properties {"priority" (get r :block/priority)})) result)))
   :collapsed? false
}
#+END_QUERY

I’m just missing the piece how to exclude the “Plan my day” and all other templates containing TODOs.

So you mean excluding by property template:: of either:

  • the parent-block:
    (not
      [?b :block/parent ?parent]
      [?parent :block/properties ?props]
      [(get ?props :template)]
    )
    
  • any ancestor block:
    (not
      (ancestor ?ancestor ?b)
      [?ancestor :block/properties ?props]
      [(get ?props :template)]
    )
    
    • This needs a recursive ancestor rule:
      :rules [
      	[(ancestor ?a ?b)
      	 [?b :block/parent ?a]
      	]
      	[(ancestor ?a ?b)
      	 [?b :block/parent ?t]
      	 (ancestor ?a ?t)
      	]
      ]
      
      • And this needs % at the end of :in

Great, thank you @mentaloid !!

For reference, here’s the full query:

{:title "Query Excluding Template Sub-blocks"
 :query [:find (pull ?b [*])
         :in $ %
         :where
         [?b :block/marker ?marker]
         [(contains? #{"TODO" "DOING" "NOW"} ?marker)]
         (not [?ancestor :block/properties ?props]
              [(get ?props :template)]
              (ancestor ?ancestor ?b))]
 :rules [[(ancestor ?a ?b)
          [?b :block/parent ?a]]
         [(ancestor ?a ?b)
          [?b :block/parent ?t]
          (ancestor ?a ?t)]]
 :collapsed? false}