Awesome addition by @CappieXL
Hi @Siferiax Thank you for sharing so much, it’s very much appreciated. I’ve finished going through https://www.learndatalogtoday.org/ but I’m still stuck on this advanced query to find all tasks that have an ancestor with the content “routine”. I’m curious if you can help.
#+BEGIN_QUERY
{:query [:find (pull ?b [*])
:in $ ?s %
:where
[?b :block/marker ?marker]
[(contains? #{"TODO"} ?marker)]
;; ancestor is true when ?ancestor is an ancestor of b
((ancestor ?b ?ancestor)
[?ancestor :block/content ?str]
[(clojure.string/includes? ?str ?s)]
)]
:inputs
["routine" [[[ancestor ?b ?ancestor]
[?b :block/parent ?ancestor]]
[[ancestor ?b ?ancestor]
[?child :block/parent ?ancestor]
(ancestor ?b ?child)]]]
}
#+END_QUERY
Do you have any tips for debugging queries or any tools that allow for deep introspection and debugging?
Thank you!
Originally posted my question here: Advanced query to get all outstanding tasks with an ancestor that contains a string
Another useful bit I’ve built to solve a task management query problem. It was mostly a compilation of things I found on this helpful thread, so I thought I’d contribute back.
In short, it finds blocks with TODO markers that are either:
- In a namespace of a specified page
- Are tagged with a page tag that is in the namespace of a specified page
I’m a bit disorganized between using page tags or namespaces, and I often want to find TODOs below a given namespace, as well as pages tagged there. This solves both.
#+BEGIN_QUERY
{:title [:h4 "Find tasks in a namespace, or things that reference a namespace."]
:query [:find (pull ?block [*])
:in $ %
:where
[?block :block/page ?page]
[?destpage :block/name "logseq"]
[?destpage :block/file ?origfile]
; it is a TODO
[?block :block/marker ?marker]
[(contains? #{"TODO", "DOING"} ?marker)]
; check either the page it's on, or the page it's on is tagged with a page that matches
(or-join [?page ?destpage]
(check-ns ?destpage ?page)
(and
[?page :block/tags ?pagetag]
(check-ns ?destpage ?pagetag)
)
)
]
:rules [
[(check-ns ?ns ?page)
[?page :block/namespace ?ns]
]
[(check-ns ?ns ?page)
[?page :block/namespace ?t]
(check-ns ?ns ?t)
]
]
}
#+END_QUERY
Thank you for this wealth of information!!
I am trying to simply filter out tasks with a specific tag (i.e. #[[Reading list]]), so that the journal query returns only those tasks marked as LATER which don’t have that specific tag.
I’m sure the solution is in here somewhere, but am getting a bit lost and would appreciate some help…
{:title "📅 LATER"
:query [:find (pull ?h [*])
:in $ ?start ?next
:where
[?h :block/marker ?marker]
[(contains? #{"LATER" "TODO"} ?marker)]
[?h :block/page ?p]
[?p :block/journal? true]
(not [?h :block/refs ?t]
[?t :page/name "reading list"])
[?p :block/journal-day ?d]
[(> ?d ?start)]
[(< ?d ?next)]]
:inputs [:365d :today]
:result-transform (fn [result]
(sort-by (fn [h]
(get h :block/priority "Z")) result))
:group-by-page? false
:collapsed? true}]}
:view (fn [r] [:pre.code (pprint r)])
Will show you the output of your query more directly which can help.
I’ll have a look at the topic and reply there
Does the query you posted work for you? Or do you need further help?
Thank you for following up!
The query I posted is working perfectly. Was sharing in case anyone else needs it.
First of all, thanks @Siferiax for sharing all these queries.
I have the following problem: I organized my projects as separate pages where all have a tags:: project
tag. My tasks then refer to the individual projects, e.g.:
TODO start with #[[projectA]]
TODO start with #[[projectB]]
page for projectA
:
- tags:: project
- this is the project page for #[[projectA]]
page for projectB
:
- tags:: project
- this is the project page for #[[projectB]]
I have a query to show all project related tasks: all tasks that refer to pages that have a tags:: project
:
It looks like this:
#+BEGIN_QUERY
{:title [:h3 "Tasks Referencing a page with tags:: project"]
:query [:find (pull ?b [*])
:where
[?t :block/name "project"] ; always lowercase
[?p :block/tags ?t] ; all pages with tag name "project"
[?b :block/refs ?p] ; all blocks that refs one of the pages in ?p
[?b :block/marker ?mref]
[(contains? #{"TODO" "DOING"} ?mref)]
]
:breadcrumb-show? false ; don't show the parent blocks in the result !important, due to result-transform the grouping is lost, and so you will be left with a simple list of TODO items. having those parents blocks mixed in may make the list more confusing. (setting this to true won't show the page btw!)
:collapsed? false
}
#+END_QUERY
Now I want a query which shows me all tasks that do not refer to a page with a tags:: project
tag.
I tried to play around with not
… however, I can’t manage to write the query correctly. Any help would be greatly appreciated.
Thanks
You’re very welcome
So not in the “where not exists” sense is a bit different than a straight forward “not this”.
For “where not exists” we need first define the subset to exclude. This means the whole set needs to be within the not.
So for your query.
Step 1. move the clauses for ?b is a task to the top (we cannot start with not). The last two lines of your where clause.
Step 2. everything else goes into the not clause.
Just the where part then becomes:
[?b :block/marker ?mref]
[(contains? #{"TODO" "DOING"} ?mref)]
(not
[?t :block/name "project"] ; always lowercase
[?p :block/tags ?t] ; all pages with tag name "project"
[?b :block/refs ?p] ; all blocks that refs one of the pages in ?p
)
Essentially in the not you say give me all pages that are tagged project and then make sure ?b does not reference those.
It becomes “all this” is not true at the same time.
Whereas if you would only put the ?b references ?p in the not clause it would be ?b does not reference ?p. Well if ?b references say ?d it would be true even if ?b also references ?p.
That’s a bit confusing and complicated to wrap your head around.
Consider that :block/refs
has a list of references. When you say “not ?p” it basically asks is there anything in that list that isn’t ?p. Well the answer, for a task at least, is always yes. The marker itself is a page that is in that reference list.
By putting all the statements in the not we essentially make a separate query which gives all blocks that are referencing a project page. Then with our not clause we say subtract those from the set we already have.
I hope that makes any sort of sense
It has been quite a journey for me to grasp myself, so I’m hoping to explain the concept in a way that is understandable.
If you still don’t get it, just remember that if not enough is filtered, statements are missing in your not clause.
Thanks for the help with the query and for taking the time to write the explanation! I hope that I can solve my where not exists
problems in the future by myself.
Hi all.
Anybody can help to do a query to collect all the TODO scheduled for THIS WEEK? I know I can use the next 7 days, but I would like to see the task for this week (from Monday to Sunday).
Is it possible also for THIS MONTH?
Thanks in advance
Hi,
I thought there was a topic on this but I can’t find it
So we have no idea what week it is in the advanced query language. So there is no way to get a strict week out of it.
We can do months though! Here’s an example of that.
#+BEGIN_QUERY
{:title [:h3 "Tasks this month"]
:inputs [:today]
:query [:find (pull ?b [*])
:in $ ?today
:where
[?b :block/marker ?m]
[(contains? #{"TODO" "LATER"} ?m)]
[?b :block/scheduled ?d]
[(str ?today) ?strday]
[(subs ?strday 0 6) ?jm]
[(str ?jm "01") ?strstart]
[(* ?strstart 1) ?start]
[(str ?jm "31") ?strend]
[(* ?strend 1) ?end]
[(<= ?start ?d ?end)]
]
}
#+END_QUERY
Thanks as usual.
I got excited when I found +1w or +0W thinking could be next and this week, but it is not the case
I hope in the future they will add something for the week
@Siferiax one more thing how to add bold or highlight on the title of the advance query?
:title [:h3 "Tasks this month"]
Bold: :title [:b "Tasks this month"]
Highlight: :title [:mark "Tasks this month"]
Both: :title [:b [:mark "Tasks this month"]]
Found the topic:
Thanks @Siferiax
I used it, but I got an error:
Query for unknown vars: [?b]
is it working for you?
Working now! there was two *somewhere.
Hi all. Is there a way to make the Todo scheduled appear only after the date and time is overdue? I know how to do only date, what about time?
Unfortunately no. Time is not stored as an attribute and so is just plain text in the block content.
Likewise the only input we have for current time is an epoch timestamp and not plain text.
I feel the scheduled/deadline implementation is very lacking in that sense.
Should be a feature request to make the time an attribute in the form of epoch timestamp as well so we can more easily get the correct tasks.
thanks.
I agree that it is a pity