Queries for task management

Only way is to substitute empty with “A”.
There should be sort examples that do this already.
From the top of my head (get r :block/priority "A")
This would intermingle the priority A tasks with the empty priority tasks though, as A is the first letter of the alphabet :sweat_smile:
I don’t know if something like “1” would work, but might be worth a shot.

Thank Siferiax

I searched for examples and didn’t find, maybe I missed…
Is it something with assoc function?
Ooof that bit complex for me :person_shrugging:
If you can link to me relevant code it will be great not urgent :wink:

:result-transform (fn [result] (sort-by (fn [r] (get-in r [:block/priority] "A")) result))

Or change “A” to “1” as mentioned.
It’s also in the default config sort-by-priority code, only there the default value used is “Z”.

@Siferiax thanks a lot!

It works great :slight_smile:
I can now initiate long waiting kanban board work flow, without fear newly taks will be missed :heart:

:result-transform (fn [result] (sort-by (fn [r] (get-in r [:block/priority] “1”)) result))

1 Like

I actually ended up finding a good use for :current-page - I’m using Embed blocks for different sections of my journals, and have those embed blocks in a daily template - so I only edit the Query once and it populates across all my journals, but still gets the Current page content - absolutely brilliant, I’m loving Logseq more every day!

1 Like

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

1 Like

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
1 Like

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}]}
1 Like

: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 :slight_smile:

Does the query you posted work for you? Or do you need further help?

2 Likes

Thank you for following up! :hugs:
The query I posted is working perfectly. Was sharing in case anyone else needs it.

1 Like

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 :slight_smile:
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 :smiley:
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.

1 Like

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 :smiley:
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

1 Like

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 :frowning:

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"]]

1 Like