Advanced query to find tasks based on namespaces and properties

Unfortunately I use namespace and page-property mixed.

For example: work/HR

But work also functions as page property.

For example

Project 1

  • area:: work

How can I retrieve tasks on both sides of the word work in this example? Can I combine this into one query?

Thank you!

Do you have some examples of tasks you like to retrieve?
I don’t understand what “tasks on both sides of the word work” means.

If I understand it correctly, the simplest approach based on what you describe would be to change your instances of area:: work to area:: [[work]] or area:: #work
Then, a query for every task within the namespace work should give you what you need: Advanced Query that pulls all reference AND recursive name spaces - Customization / Look what I built - Logseq

This might currently have some rough edges, I’ll leave what I have so far…
this should match tasks in the given namespace, and tasks under parents with the area tag set to the namespace
… re-reading the original requirement, maybe this instead

#+BEGIN_QUERY
{
:title [:h3 "Project Tasks"]
:inputs ["work"]           ; hard coded namespace
; :inputs [:current-page]  ; or this if using query on namespace root
:query [
  :find (pull ?b [*])
  :in $ ?namespace
  :where 
    [?b :block/marker]
    (or-join [?namespace ?b]     
      (and  ; does block page belong to namespace?
          [?b :block/page ?page]
          [?page :block/namespace ?ns]
          [?ns :block/original-name ?namespace]
      )
      (and   ; this might not match your original requirement
             ; match parent block (doesnt have to be a page) 
             ; with area property with namespace
          [?b :block/parent ?par]
          [?par :block/properties ?props]
          [(get ?props :area) ?area]
          [(= ?area ?namespace)]
      )
      (and ; does block page have area property with namespace?
          [?b :block/page ?page]
          [?page :block/properties ?props]
          [(get ?props :area) ?area]
          [(= ?area ?namespace)]
      )
    )
]
;:view :pprint  ; debug view if needed
}
#+END_QUERY

image

1 Like

Oh, sorry. I mistyped it. If possible, I’d like to pull tasks from both pages with one query.

Example:

page1: work/HR
todo1

page2: Example project
area:: work
todo2

Dear @Siferiax , I think this query of yours is the closest. Can you modify it so it doesn’t use the page itself but all aliases? E.g. [[work]]. I want to find all todos with “work” namespaces, tags, and page properties.

r#+BEGIN_QUERY
; see https://discuss.logseq.com/t/advanced-query-that-pulls-all-reference-and-recursive-name-spaces/21275/8
{:title [:h3 "Recursive Namespace + Alias Tasks" ]
  :query [:find (pull ?b [*])
    :in $ ?inputpage %
    :where
    [?b :block/marker ?m]
    [(contains? #{"NOW" "LATER" "TODO" "DOING"} ?m)]
    (or-join [?b ?inputpage]
      (and ; Is de page the task is on part of the namespace of the input page?
        [?b :block/page ?p]
        [?ns :block/name ?inputpage]
        (check-ns ?ns ?p)
      )
      (and ; Does the task refer to the input page in its lineage?
        [?p :block/name ?inputpage]
        [?b :block/path-refs ?p]
      )
      (and ; Does the task refer to an alias in it's lineage, either of the input page or a page in its namespace?
        (or-join [?p ?inputpage]
          (and
            [?ns :block/name ?inputpage]
            (check-ns ?ns ?p)
          )
          [?p :block/name ?inputpage]
        )
        [?p :block/alias ?a]
        [?b :block/path-refs ?a]
      )
    )
  ]
  :result-transform (fn [result]
    (let [sorted-result (sort-by (fn [h] (get h :block/marker)) > result)]
    (map (fn [m] (assoc m :block/collapsed? true)) sorted-result)))
  :group-by-page? yes
  :breadcrumb-show? yes
  :inputs [:current-page]
  :collapsed? false
  :rules [
    [(check-ns ?ns ?p)
      [?p :block/namespace ?ns]
    ]
    [(check-ns ?ns ?p)
      [?p :block/namespace ?t]
      (check-ns ?ns ?t)
    ]
  ]
}
#+END_QUERY

So I eh… reconsidered that entire query, as I was trying to adjust it to add the properties criteria.

If you place this query on the work page (or any other page for that matter). It’ll get all tasks related to the page the query is on.
You can change the input to any lower case page name to get tasks for that specific page, while the query is elsewhere.

Let me know how it goes!

#+BEGIN_QUERY
{:title [:h3 "All tasks related to the current page" ]
 :inputs [:current-page]
 :query [:find (pull ?b [*])
  :in $ ?inputpage %
  :where
; get all tasks with a specific status
   [?b :block/marker ?m]
   [(contains? #{"NOW" "LATER" "TODO" "DOING"} ?m)]
; get the input page, its aliases and its namespaces and their aliases
   (or-join [?p ?inputpage]
     [?p :block/name ?inputpage] ; ?p is just the input page
     (and
       [?a :block/name ?inputpage]
       [?a :block/alias ?p] ; ?p is the alias of the input page
     )
     (and
       [?ns :block/name ?inputpage]
       (check-ns ?ns ?p) ; or ?p is a page in the namespace of the input page
     )
     (and
       [?ns :block/name ?inputpage]
       (check-ns ?ns ?a)
       [?a :block/alias ?p] ; or ?p is the alias of a page in the namespace of the input page
     )
   )
; determine if the task belongs to the input page (and related pages)
   (or-join [?b ?p ?inputpage]
     (and ; Does the page the task is on refer to the input page in its properties?
       [?x :block/refs ?p]
       [?x :block/pre-block? true]
       [?x :block/page ?y]
       [?b :block/page ?y]
     )
     (and ; Is the page the task is on related to the input page?
       [?b :block/page ?p]
       (not [?p :block/name ?inputpage]) ; we don't need the tasks on the input page itself
     )
     [?b :block/path-refs ?p] ; Does the task refer to the input page in its lineage?
   )
 ]
 :group-by-page? false
 :breadcrumb-show? false
 :result-transform (fn [result]
   (let [sorted-result (sort-by (fn [h] (get h :block/marker)) > result)]
   (map (fn [m] (assoc m :block/collapsed? true)) sorted-result))
 )
 :rules [
   [(check-ns ?ns ?p)
     [?p :block/namespace ?ns]
   ]
   [(check-ns ?ns ?p)
     [?p :block/namespace ?t]
     (check-ns ?ns ?t)
   ]
 ]
}
#+END_QUERY

1 Like

You are amazing, thank you.

I’m really sorry for my ignorance, but how should I modify the query if I want to retrieve tasks from another page? Where should I type the name of the page (in my example: work) I am requesting?

Change this part to: :inputs ["work"]
Or place the query on the page work if you prefer. (As seen in my screenshot)

And don’t worry about it :slight_smile: we all need to learn things the first time.

2 Likes

I have explored several options, but have not yet come across this one. :sweat_smile:

This query is crucial for Logseq project management (at least in my workflow), but I feel this one is generally a gem. It would be even more helpful if it displayed the page and breadcrumbs.
So, I changed these two lines:

:group-by-page? yes
:breadcrumb-show? yes

Wow, and wow!
Thank you.

The correct syntax is true, not yes.
Also if you want to see them by Page, you’ll need to remove the result-transform, as that will override the group-by-page setting.

1 Like

I was happy I could figure out something independently, but I can’t :slight_smile: