Hide blocks with specified tag in queries

Hi,
i thought it’s trivial, but i can’t get it to work… I’ve got notes like below:

- some block #test
	- block A
		- AAA
		- aaa
	- block B #archive
		- bbb
		- bbb
	- bloc C
		- CCCC
		- cccc #archive
- some second block
	- block D
		- ddd #test
		- DDD

now, i want to build a query, which’ll show me all block with #test tag, without blocks with #archive.

I thought, that simple:

{{query (and [[test]] (not [[archive]]))}}

should do the job, but that shows me only
Screenshot_20240512_012942

Could someone help me with that?

1 Like

What should it show instead?

I’d like to see everything, what isn’t marked as archive, so in above example:

- some block #test
	- block A
		- AAA
		- aaa
	- bloc C
		- CCCC
- some second block
	- block D
		- ddd #test
	

This is not possible with a simple query, but it is with an advanced one.

  • Based on your example, that query should return all non-archived blocks that either:
    • contain tag #test
      • e.g. blocks some block and ddd
    • have an ancestor block that contains tag #test
      • e.g. blocks aaa and CCCC
    • have a descendant block that contains tag #test
      • e.g. blocks some second block and block D
  • However, could you clarify the following things in your example:
    • What exactly qualifies block DDD to be part of the results?
      • The above cases don’t capture it. What other case should be included to capture it?
    • What should happen with the descendants of #archive (i.e. blocks bbb) if they happen to contain tag #test themselves?

Sorry, my mistake - block DDD shouldn’t be visible (i’ve already edited previous post)

about “some second block” - it doesn’t have to be visible as long as i can see “ddd” (it’s even better when it’s hided), so we can make it a bit simpler removing your third condition

tag #archive is the most important, so it should always hide block, which contains it (and all subblocks of that block), regardless occurrence of #test tag

Try this:

#+BEGIN_QUERY
{:query [:find (pull ?b [*])
   :in $ %
   :where
     [?yes :block/name "test"]
     (or-join [?b ?yes]
       [?b :block/refs ?yes]
       (and
         (ancestor ?a ?b)
         [?a :block/refs ?yes]
       )
     )
     (not
       [?no :block/name "archive"]
       (or-join [?b ?no]
         [?b :block/refs ?no]
         (and
           (ancestor ?a ?b)
           [?a :block/refs ?no]
         )
         (and
           (descendant ?d ?b)
           [?d :block/refs ?no]
         )
       )
     )
 ]
 :inputs [
   [
     [
       [ancestor ?a ?b]
       [?b :block/parent ?a]
     ]
     [
       [ancestor ?a ?b]
       [?parent :block/parent ?a]
       (ancestor ?parent ?b)
     ]
     [
       [descendant ?d ?b]
       [?d :block/parent ?b]
     ]
     [
       [descendant ?d ?b]
       [?d :block/parent ?child]
       (descendant ?child ?b)
     ]
   ]
 ]
}
#+END_QUERY
2 Likes

Works as expected, thank you for your help

Hey! I thought that would show « some block # test » but hide the child block « block B #archive » since it’s excluded, kind of like the Linked References Filter Pane ! Your solution simply excludes « some block #test » from the query results although it would be relevant as it’s not tagged with #archive. How can I adjust the query to get that result ? = excluding certain child blocks when expanding the block parent as part of the query results in the style of the built-in Filter Pane. Thanks

  • Queries:
    • do not show/hide blocks
    • simply filter blocks
  • If you need control on what is rendered, should:
    • use :view
    • maybe use :result-transform as well
    • be prepared for some quite challenging clojurescript
  • Default rendering has only two options:
    • List view: For every block that passes the filtering, the results show (with limited customization options):
      • all its ancestors (first line only)
      • all its descendants (but without repetitions)
    • Table view:
      • Lists individual blocks.
      • Sacrifices the hierarchical appearance.
      • May fit your need.
        • If you want help with this, you should provide specific desired results.

Thank you for your response. I actually want exactly what @marcink had in mind, which is a filtered hierarchy (WorkFlowy-style), giving us this result :

  • some block #test
    • block A
      • AAA
      • aaa
    • bloc C
      • CCCC
  • some second block
    • block D
      • ddd #test

Your proposed query only goes for the deepest nodes and shows the parents as breadcrumbs. It’s not quite it. Thank you!

Try this:

#+BEGIN_QUERY
{:query [:find (pull ?b [*])
   :in $ %
   :where
     [?yes :block/name "test9"]
     (or-join [?b ?yes]
       [?b :block/refs ?yes]
       (and
         (ancestor ?a ?b)
         [?a :block/refs ?yes]
       )
       (and
         (descendant ?d ?b)
         [?d :block/refs ?yes]
       )
     )
     (not
       [?no :block/name "archive"]
       (or-join [?b ?no]
         [?b :block/refs ?no]
         (and
           (ancestor ?a ?b)
           [?a :block/refs ?no]
         )
         (and
           (descendant ?d ?b)
           [?d :block/refs ?no]
         )
       )
     )
  ]
 :inputs [
   [
     [
       [ancestor ?a ?b]
       [?b :block/parent ?a]
     ]
     [
       [ancestor ?a ?b]
       [?parent :block/parent ?a]
       (ancestor ?parent ?b)
     ]
     [
       [descendant ?d ?b]
       [?d :block/parent ?b]
     ]
     [
       [descendant ?d ?b]
       [?d :block/parent ?child]
       (descendant ?child ?b)
     ]
   ]
 ]
}
#+END_QUERY

You may experiment with removing some conditions from :where .