Help Navigating & Converting Extensive Block References

Hi all,

I’ve used many block references to connect various types of information to a single project topic. Now, the list of linked (block) references to that block has grown very long and is hard to read or make sense of.

Here’s the problem:

  • You can’t filter or search in the list of backlinks the way you can with regular page references .
  • You can’t full text search or query the graph for block references as they don’t return the blocks that reference the original block . Referencing blocks contain only the UUID of the target block, not its actual text, and thus search or queries only find the original block, not its backlinks. So you can’t use search or queries to filter block backlinks either.

My questions:

  1. Does anyone have suggestions for navigating long lists of block references more effectively?
  2. Is there an easy and safe way to convert block references into regular page references, so I can take advantage of filtering, search, and queries on the project page?

Thanks a lot in advance!

Linked references provide only a basic means for getting informed about the existence of connections. Working with those connections needs better tools.

  • Converting needs scripting, so it is not a solution of preference.
  • Advanced queries support searching for and filtering block references in both directions and by actual text.
    • If you provide some example pages, blocks, and searching criteria, we can construct for you a query that returns only the desired results and can be adjusted for all similar cases.
      • If we reach the actual limitations of queries, we can still inform the query with a macro or employ the full power of a kit.

Thanks so much! Here’s some simplified example pages to work with:

Target page (index I want to query against)

Page: Project A
- Introduction Project A
- Data Analysis Project A
- Discussion Project A

Referencing blocks (from other pages)

Page: Test for block reference query
- From other pages like this, I want to take notes and link them
    - to ((UUID-of-Discussion-Project-A)) if they are relevant to the Discussion. This could contain a statement on topic X from some other article relevant to Project A.
    - TODO [#A] or to ((UUID-of-Data-Analysis-Project-A)). Here I could have a note about [[logistic regression]] that is relevant to the data analysis. Tagged with todo and priority A.
- Somewhere else I may link
    - TODO [#A] or to ((UUID-of-Data-Analysis-Project-A)) about a bit of code in my code repository on that I may need as reference at some point.

Note: the mentions of “Discussion Project A” and “Data Analysis Project A” in the referencing blocks above are block references (i.e., ((UUID))), not page references.

What I’d like is a query that helps me find blocks that reference these two blocks (by UUID), and lets me filter for things like:

  • Data Analysis Project A + tag [[logistic regression]]
  • Data Analysis Project A + status TODO
  • Discussion Project A + full-text match "topic X"

Thanks again — any help with query construction or a macro setup would be hugely appreciated!

Could begin with something like this:

#+BEGIN_QUERY
{
 :query [:find (pull ?b [*])
   :where
     [?project-a :block/original-name "Project A"]
     [?target :block/page ?project-a]
     [?target :block/content "Data Analysis Project A"]
     [?target :block/uuid ?uuid]
; replace this comment-line with other conditions
     [?b :block/content ?content]
     [(clojure.string/includes? ?content ?uuid)]
 ]
}
#+END_QUERY
  • It should return the block references of Data Analysis Project A.
  • Should then further filter them (specifically ?b) according to your needs.
  • But the last two conditions are slow, so you should perform the filtering before these two lines, so as to prevent excessive full-text searching.

Thanks again! I tried the version you proposed, but unfortunately it just returns “No matched results”.

To confirm:

  • The block I want to track and then filter is titled "Data Analysis Project A" — it’s a block, not a page, and it’s referenced via ((UUID)) in other places. The block exists with that exact content.
  • The referencing blocks use standard block references and display the referenced block correctly in the UI.
  • I tried getting help via AI, but couldn’t quite get a working query together.

Would really appreciate help correcting or reworking the query so it reliably picks up those references. Thanks!

  • My version works to me.
    • I copied the blocks from your post.
    • You could possibly try it in a new simpler graph, just in case.
  • Should debug the situation:
    • Remove some conditions to simplify the query.
      • Start from the last one and then go upwards.
      • When needed, adjust :find to return something meaningful.
        • e.g. ?target or ?project-a
    • Keep going until some results start appearing.
    • Share here the partially working query.

Thanks for the help and suggestions — they really helped me work through this! :pray:

  • The issue was with looking up the UUID.
  • With help of AI, I ended up with this version.
  • Does this make sense to you?
#+BEGIN_QUERY
{
 :query [:find (pull ?b [*])
  :where
    [?target-block :block/content ?target-content]
    [(clojure.string/includes? ?target-content "Data Analysis Project A")]
    [?b :block/refs ?target-block]

    ;; Optional: Uncomment to filter by TODO
    ;; [?b :block/marker ?marker]
    ;; [(= ?marker "TODO")]

    ;; Optional: Uncomment to filter by tag
    ;; [?b :block/refs ?tag]
    ;; [?tag :block/original-name "tag"]

    ;; Optional: Uncomment to filter by priority (like [#A])
    ;; [?b :block/priority ?priority]
    ;; [(= ?priority "A")]
 ]
}
#+END_QUERY

It does make sense, but it will become slow as the graph gets bigger. Try this improvement:

#+BEGIN_QUERY
{
 :query [:find (pull ?b [*])
   :where
     [?project-a :block/original-name "Project A"]
     [?target :block/page ?project-a]
     [?target :block/content "Data Analysis Project A"]
     [?b :block/refs ?target]
 ]
}
#+END_QUERY

That again returns “No matched results”.

I now doubt that.

  • If you have Developer mode on, you can check the actual content.
  • Alternatively, check directly the markdown of page [[Project A]].
  • If it turns out that the block contains hidden content, should either:
    • replace string "Data Analysis Project A" with the full markdown content
    • replace line [?target :block/content "Data Analysis Project A"] with AI’s partial suggestion:
      [?target :block/content ?content]
      [(clojure.string/includes? ?content "Data Analysis Project A")]
      
      • This one is slower, but not by much.

This is copied from the markdown file Project A.md,
it contains the id:: in addition:

  • Introduction Project A
  • Data Analysis Project A
    id:: 6807eded-e4ce-42b2-a439-964e2b3cb1ac
  • Discussion Project A
    id:: 6807edc6-ab2d-478d-80ac-98d42e5b0e3d

Replacing the line with AI’s suggestion works.

With the project page in my real graph, I am running in issues query performance. LogSeq becomes nearly unresponsive on load of this page even if the querries are on collapsed blocks.

Setup:

  • Page: Project A
    • Introduction Project A (collapsed)
      • query for blocks referencing this section
    • Methods Project A (collapsed)
      • similar query
    • …7 such queries total, covering ~250 referenced blocks.

Questions:

  1. Is there any way to defer or delay execution of queries? Should collapsing the block do this?
  2. Or is this the point where I should consider converting to page references instead of block references?

Would love to hear if anyone’s found a good pattern here.

  • Queries in collapsed blocks don’t run at all.
    • Should be truly collapsed blocks, in the normal Logseq way, not through some customization.
  • As already stated, text searching can be slow.
    • Therefore it should be placed as late in the query as possible.
      • AI failed to do that in the shared query.
  • If a query returns many results, it will be slow in rendering, even if it is fast in execution.
    • This sounds like being your current case.
    • Actually such queries are of little usage and should be further filtered.
    • It is possible to construct queries that display only either:
      • the first few results
      • the number of the found items, not the items themselves