FInd nested TODOs

In a fresh Graph I add the following data:

- This is a block that is connected to [[Project A]].
	- Here is a Task that is relevant to this project, but it's not directly tagged with :
		- TODO Write Stuff down
- On the other hand here is a Task that is tagged with the project:
	- TODO Do Stuff 
- TODO And here is a unrelated Task that should not be found

I can’t figure out a query that finds TODO Write Stuff down and TODO Do Stuff - both Tasks are somehow connected to Project A or aren’t they?

Can someone help me with a query? Thanks!

I got you covered in this thread:

If you can’t figure out how to adapt it, let me know!

Thanks! This works fine on the page - how would I change this to work elsewhere? I tried:

#+BEGIN_QUERY
{:title ["Query by page & alias"]
 :query [:find (pull ?b [*])
   :in $ ?page %
   :where
     [?b :block/marker "TODO"]
     [?p :block/name ?page]
     (or-join [?b ?p]
       (check-ref ?p ?b) 
       (and 
          [?p :block/alias ?a]
          (check-ref ?a ?b)
       )
     )
 ]
 :rules [
   [(check-ref ?p ?b)
     [?b :block/refs ?p]
   ]
   [(check-ref ?p ?b)
     [?b :block/parent ?t]
     (check-ref ?p ?t)
   ]
 ]
 :table-view? false
 :inputs ["Project A"]
}
#+END_QUERY

in my Journal, but this didn’t work. Thanks!

@Siferiax not sure if you can help, but I have a very similar issue

I essentially want to make a query like this one:

 - Meeting notes
   - TODO aaaa
   - bbbbb
      - TODO ccccc
      - dddddd
         - TODO eeeee
 - <query here - would return all three TODOs>

Ideally the query wouldn’t need to change depending on the title of the block (that way I can just paste in the query as part of my meeting template and see all the actions at the end of the meeting)
Would love any help you could provide!! :slight_smile:

:block/name is always lower case.
So to accomplish that your input should be "project a".

Edit: otherwise you can use :block/original-name which is the page name as you see it. Whichever option is easier for you.

If you indent the query in it, you can run it based on it’s parent block as input.
So for example:

- parent block title
   - meeting notes
     - stuff
   - query

Or make meeting notes the parent, whatever you prefer.
You can then use this as the query:

#+BEGIN_QUERY
{:title ["Query by page & alias"]
 :query [:find (pull ?b [*])
   :in $ ?parent %
   :where
     [?b :block/marker "TODO"]
     (check-parent ?parent ?b)
 ]
 :rules [
   [(check-parent ?parent ?b)
     [?b :block/parent ?parent]
   ]
   [(check-parent ?parent ?b)
     [?b :block/parent ?t]
     (check-parent ?parent ?t)
   ]
 ]
 :inputs [:parent-block]
}
#+END_QUERY

Disclaimer: I did not test this. I wrote it all on my phone by memory.

3 Likes

Amazing, that worked perfectly - thanks so much, you’re a lifesaver! :slight_smile:
Also incredible you wrote that on your phone by memory!!

1 Like

Since it was featured in Logseq Times, I’ll just add to this post to say I’m a dumdum and there is an attribute for this, making the query A LOT simpler!

This is for the query based on page reference, not the one based on parent blocks.

#+BEGIN_QUERY
{:title ["Query by page & alias"]
 :query [:find (pull ?b [*])
   :in $ ?page
   :where
     [?b :block/marker "TODO"]
     [?p :block/name ?page]
     (or-join [?b ?p]
       [?b :block/path-refs ?p]
       (and 
         [?p :block/alias ?a]
         [?b :block/path-refs ?a]
       )
     )
 ]
 :result-transform :sort-by-priority
 :table-view? false
 :inputs [:query-page] ; alternatively use the lower-case name of a page.
}
#+END_QUERY

This query uses :block/path-refs to find all references in all parent blocks, including the block itself.
As opposed to :block/refs which only looks at the references of the block itself.

1 Like

Thanks so much again for your help @Siferiax, your work is amazing!!
I’m sure this is covered before, but I’m struggling to find an answer to the below two questions:

  1. I’d like to create a query that returns all TODOs wherever “abc” is included in a tag, until now I’ve been defaulting to the below but feel like there’s a more efficient way to write this:
#+BEGIN_QUERY
{:title [:h3 "abc tasks (TODO)"]
 :query [:find (pull ?b [*])
         :where
         (task ?b #{"TODO"})
         [?b :block/page ?p]
         (or [?r :block/original-name "abc123"]
               [?r :block/original-name "abc456"])
             (or [?b :block/path-refs ?r]
                 [?p :block/tags ?r])]}
#+END_QUERY
  1. I’m trying to create a query like the above but only include the TODO if it has a scheduled or deadline included (and then list from most urgent to least urgent)
    Again sorry if these answers already exist somewhere!!

There’s a lot of information scattered about and a lot of specific situations to cover. So don’t worry about it!

There are two ways. Regular expressions or clojure string functions. I went with the clojure one as it is easier.

#+BEGIN_QUERY
{:title [:h3 "abc tasks (TODO)"]
 :query [:find (pull ?b [*])
         :where
         (task ?b #{"TODO"})
         [?b :block/page ?p]
         [?r :block/original-name ?name]
         [(clojure.string/includes? ?name "abc")]
             (or [?b :block/path-refs ?r]
                 [?p :block/tags ?r])]}
#+END_QUERY

We need an extra check and a result-transform for the sorting.

#+BEGIN_QUERY
{:title [:h3 "abc tasks (TODO)"]
 :query [:find (pull ?b [*])
         :where
         (task ?b #{"TODO"})
         (or 
           [?b :block/scheduled _]
           [?b :block/deadline _]
         )
         [?b :block/page ?p]
         [?r :block/original-name ?name]
         [(clojure.string/includes? ?name "abc")]
             (or [?b :block/path-refs ?r]
                 [?p :block/tags ?r])
 ]
 :result-transform (fn [result] 
  (sort-by 
    (min 
      (fn [d] (get d :block/scheduled 99999999) ) 
      (fn [d] (get d :block/deadline 99999999) ) 
    )
   result
  )
 )
}
#+END_QUERY

I used the sorting from here for this:

PS. Sorry if something doesn’t work. I didn’t check. Let me know if you experience any issues.

1 Like

Perfect as always, thank you so much @Siferiax
Your patience and kindness with people like me on these forums is an absolute gift :blush:

1 Like