Query to find orphan blocks?

Is it possible to have a query which will pick up blocks where the block (and any of its nested children) do not have any page / tag reference (in any direction)?

Motivation is that I (as many others) write in Journals window by default, and it’s easy for some notes to slip through the cracks. With this query, it would be easy to find them.

I’ve seen somebody suggested using something like #fleeting when working with such block (when you’re not sure where they’d go), but with such a query, one wouldn’t even need to remember to tag it :slight_smile:

Something like this:

#+BEGIN_QUERY
{
 :query [:find (pull ?block [*])
 :in $ %
 :where
   [?block :block/page ?page]
   (not [?block :block/refs])
   (not
     (descendant ?d ?block)
     [?d :block/refs]
   )
 ]
 :inputs [
   [
     [
       [descendant ?d ?b]
       [?d :block/parent ?b]
     ]
     [
       [descendant ?d ?b]
       [?d :block/parent ?parent]
       (descendant ?parent ?b)
     ]
   ]
 ]
}
#+END_QUERY

Thank you for replying! This is close to what I want - is it possible to NOT pick up blocks this picks up blocks e.g. this block talks about [[logseq]]?

Sorry, I don’t understand your question.

No problem, let me try to clear it up. Appreciate you sticking with me :slight_smile: The idea is that sometimes I make quick blocks in my daily journal and if I forget about them. And then it’s really difficult to find them, because they’re not connected to anything else in my graph.

So the query should pick up blocks like this

- single block

- or a block with children
  - as long as its children
  - do not have any page references
  - or tag references
  - or are not referenced by their ID anywhere?

id:: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
- block with unused id

ideally, the query should return only top-level blocks, i.e. both single block and or block with childer but not as long as children to avoid duplicating the results

The query should NOT pick up any of these

- blocks referencing a [[page]]

- blocks that have a #tag

- blocks that have children
  - that either reference a [[page]]
  - blah

- blocks that have children
  - or reference a #tag
  - blah

If not to difficult, it would be good to exclude reference / embed by id. So these shouldn’t appear on the query as well

id:: bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb
- this block is referenced (so should not be returned in query results)

id:: cccccccc-cccc-cccc-cccc-cccccccccccc
- this block is embedded (so should not be returned in query results)

- ((bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb))

- {{embed ((cccccccc-cccc-cccc-cccc-cccccccccccc))}}

As I’ve been typing this, I’ve realised that the query should only search in Journals, as it’s only there the unfiltered notes will be.

Try this one:

#+BEGIN_QUERY
{
 :query [:find (pull ?block [*])
 :in $ %
 :where
   [?page :page/journal? true]
   [?block :block/parent ?page]
   (not [?block :block/refs])
   (not [?other :block/refs ?block])
   (not
     (descendant ?d ?block)
     (or-join [?d]
       [?d :block/refs]
       [?p :block/refs ?d]
     )
   )
 ]
 :inputs [
   [
     [
       [descendant ?d ?b]
       [?d :block/parent ?b]
     ]
     [
       [descendant ?d ?b]
       [?d :block/parent ?parent]
       (descendant ?parent ?b)
     ]
   ]
 ]
}
#+END_QUERY
4 Likes

That’s perfect, thank you so much!

This query is wonderful, thanks a lot! I have a question though. Is it possible to have this query not to render empty blocks?

At the end of :where add four lines like these:

     )
   )

   (not
     [?block :block/content ?content]
     [(= ?content "")]
   )

 ]
 :inputs [
2 Likes

Worked like a charm. Thanks again, @mentaloid

Would it be possible for the query to show the results in ascending journal file name order? (YYYY_MM_DD) (oldest first).

Apparently, for now, it’s listing the pages in descending order (most recent first).

Thanks in advance!

If you search the forum, there are many results, usually this one:
:result-transform (fn [result] (sort-by (fn [r] (get-in r [:block/page :block/journal-day])) result ))
This has chronological order by :block/journal-day. If you prefer the name, replace it with :block/name.

1 Like

Thanks for the insight, @mentaloid. I tried to do some searching but I’m not fluent in the query language yet. I could not get the results I expected.

BTW, I’m not exactly sure where to put the snippet you provide. Tried at the bottom and got something. Thanks again.

Just search for :block/page :block/journal-day and you’ll get many examples. It could go here:

 ]
 :result-transform (fn [result] (sort-by (fn [r] (get-in r [:block/page :block/journal-day])) result ))
}
#+END_QUERY
1 Like