Query which excludes tasks under set of namespaces

Hello,
I use one graph for several facets of life (work, home, volunteer, …). I have also set up a task dashboard for each facet with queries to manage related tasks.

Example:

		:title [:h3 "🧯 Tasks/Home NOW"]
		:inputs ["now" "t-home"]
		;; ---- inspiration: https://adxsoft.github.io/logseqadvancedquerybuilder/
		;; ---- Get every block into variable ?block
		:query [:find (pull ?block [*])
			:in $ ?tag1 ?tag2
			;; ---- filter command
			:where
			;; ---- limit search to blocks that contain uncompleted task markers
				[?block :block/marker ?marker]
				[(contains? #{"NOW" "LATER" "TODO" "DOING"} ?marker)]
			;; ---- get block content into variable ?blockcontent
				[?block :block/content ?blockcontent]
			;; ---- get page (special type of block) into variable ?page (used later)
				[?block :block/page ?page]
			;; ---- get page name (lowercase) from the page block into variable ?pagename
				[?page :block/name ?pagename]
				( and
					;; ---- Select block if it has all the following tags or page links
					(page-ref ?block ?tag1)
					(page-ref ?block ?tag2)
				)
		]
		:result-transform (fn [result] (sort-by (fn [r] (get-in r [:block/page :block/journal-day])) result))  ; Sort by the journal date
		:table-view? false
		:breadcrumb-show? false
		:collapsed? false
	}

I would like to replace the t-{facet} inclusion criterion with an exclusion criterion that takes a list of namespaces and ignores any tasks found within. I have searched through the discussion threads, the documentation and in the web, and have spent many hours reading and trying to this myself, but I’m not getting anywhere.

Thank you for any help.

Something like this:

(not
  [?page :block/namespace ?ns]
  [?ns :block/name ?ns-name]
  [(contains? #{"name1" "name2"} ?ns-name)]
)

For multi-level namespaces, line [?page :block/namespace ?ns] can be replaced with a recursive rule, like in TODOs from parent and child pages

Thank you very much for the help. I am sorry it took me so long to get back with feedback.

I tested the code block nearly as soon as you posted it, but I could not get it to work for my use case. I think it is a combination of me:

  • not describing the intended goal well enough
  • not knowing where to place the provided code block in the query

I am trying to produce queries for task management where I can have both:

  • an indeterminate number of exclusion namespaces
  • an indeterminate number of inclusion tags

A more careful attempt at describing the goal

The goal would be to be able to filter by facet, to focus on the tasks of a single facet:

  • For instance, I have a tasks to do now query (the one I pasted above).
    • Includes any blocks with the tag #NOW and the block markers NOW, LATER, TODO or DOING.
    • I would like to review or work on my main home tasks, this means I would like to exclude any tasks within the following namespaces […]/“Physics” “Co” “Writing” “Teaching/HC/Particle Statistics” “GialloC” “logseq-meta/Templates”

Example of what I tried

Based on the provided code, one thing I tried is the following.

#+BEGIN_QUERY
{
:title [:h3 "🧯 Tasks/Home NOW"]
		:inputs ["now" "next"]
		;; ---- inspiration: https://adxsoft.github.io/logseqadvancedquerybuilder/
		;; ---- Get every block into variable ?block
		:query [:find (pull ?block [*])
			:in $ ?tag1 ?tag2
			;; ---- filter command
			:where
			;; ---- limit search to blocks that contain uncompleted task markers
				[?block :block/marker ?marker]
				[(contains? #{"NOW" "LATER" "TODO" "DOING"} ?marker)]
			;; ---- get block content into variable ?blockcontent
				[?block :block/content ?blockcontent]
			;; ---- get page (special type of block) into variable ?page (used later)
				[?block :block/page ?page]
			;; ---- get page name (lowercase) from the page block into variable ?pagename
				(not
  [?page :block/namespace ?ns]
  [?ns :block/name ?ns-name]
  [(contains? #{"Physics" "GialloC"} ?ns-name)]
)
]
		:result-transform (fn [result] (sort-by (fn [r] (get-in r [:block/page :block/journal-day])) result))  ; Sort by the journal date
		:table-view? false
		:breadcrumb-show? false
		:collapsed? false
	}
#+END_QUERY

I clearly do not understand the query, because I would have expected this to exclude any tasks created within the namespaces Physics and GialloC, however it seemed to have no effect; it kept including tasks created in a page within the namespaces “Physics” and “GialloC” as well as any tasks that had been created in other namespaces or the journal and included “Physics” or “GialloC” as tags.

Should either:

  • turn the names to lower-case, i.e. #{"physics" "gialloc"}
  • use original-name, i.e. [?ns :block/original-name ?ns-name]

Sorry, I should have said: I did try this, but it did not seem to make a difference. The query returns the same number of results. I am still seeing tasks such as:

  • TODO create new banner for end of season #GialloC
  • and TODO read XYZ from PAC1 from page Readings/Physics/
  • You misunderstand namespaces:
    • A task:
      • is not in a namespace
      • is in a block
    • A block:
      • is not in a namespace
      • is in a page
    • A page may or may not be under a namespace:
      • Page P is not in a namespace.
      • Page N/P is in namespace N.
        • or under namespace N
          • Actually N/P reads like:
            • “N over P”
            • “P under N”
    • Task TODO read XYZ from PAC1 from page Readings/Physics :
      • is not under namespace Physics
      • is in a block of a page under namespace Readings
  • I suggest that:
    • you forget about namespaces
    • check instead:
      • the original pagenames
      • along with the original tagnames
      • whether they include any of the undesired strings
        • but being aware of coincidental matches
    • like this:
      (not
        (or-join [?page ?block ?name]
          [?page :block/original-name ?name]
          (and
            [?block :block/refs ?ref]
            [?ref :block/original-name ?name]
          )
        )
        (or
          [(clojure.string/includes? ?name "GialloC")]
          [(clojure.string/includes? ?name "/Physics")]
        )
      )
      

yes, yes and yes.

  • I clearly misunderstand namespaces. I thought P was a namespace (or subnamespace) of its own. As a result, my specification of the problem was wrong.
    • Sorry for turning you around because of it.
    • Thank you very much for taking the time to explain where my understanding was lacking!
  • The solution you provided works very well. As you indicated, I will have to be very careful to avoid unintended matches.

Thank you again for all your help.