Grouping query output by tags in child block

I’m interested in making Logseq my replacement for a qualitative coding program like Atlas.ti or MAXQDA. To start, I’d like to be able to highlight paragraphs, tag the higlights individually (in child blocks) with one or more tags, and then see all the highlights grouped by those tags (which of course means a block would appear in more than one tag).

Here’s what I have so far for a query (I’m always using yellow, so that’s how I got it to find highlights - if there is a better way to get all highlights let me know), and I’m filtering out by a specific page property I’ve created called “research-topic”:

#+BEGIN_QUERY
{:query [:find (pull ?parent [*]) ?content
   :keys parent content
   :where
    [?child :block/parent ?parent]

 [?parent :block/page ?page]
     (page-property ?page :research-topic "Living Root Bridges")
(property ?parent :hl-color "yellow")

[?child :block/content ?content]

 ]
 :result-transform (fn [result]
   (map (fn [r]
     (update (:parent r) :block/properties (fn [p]
       (assoc p "Child Block" (:content r) )
     ) )
   ) result)
 )
 :remove-child-block? false
}
#+END_QUERY

I honestly don’t understand how :result-transform works (if anyone has a reference page for me to read, please comment), so I’d like to change this to do the following:

  1. actually list the name of the page it came from (right now the page column is showing up blank if I view the results as a table)
  2. group the results by any tags listed in the child blocks, as I mentioned before

Thanks in advance.

  1. Replace the 4 ?parent with ?b
    • The reason is Logseq’s quick-and-dirty implementation.
  2. Provide example blocks for us to experiment with.
    • Creating representative blocks for your particular case is demanding and time-consuming.

Thanks. Here are two sample highlight files with some sample blocks. #history is an overlapping tag between the files, and #isolated is a duplicate tag within file 1.

hls__file 1

research-topic:: Living Root Bridges
tags:: #[[living root bridge]]

- In the dense forests of a remote corner of Northeast India, an isolated tribal group have created something remarkable: scores of living bridges, which are grown, not built, from the roots of the ficus elastica species of fig tree.
  ls-type:: annotation
  hl-page:: 1
  hl-color:: yellow
  id:: 6737e88b-ba62-4311-ab2a-e851c9bea1a6
	- #isolated #self-sufficient #[[tree species]]
- It’s impossible to say how long these plantbased constructions have been around. The people who made them, the War-Khasis, had no written language until the arrival of missionaries in the early 19th century.
  ls-type:: annotation
  hl-page:: 1
  hl-color:: yellow
  id:: 6737e8c0-8e26-44b6-8c08-046a638c938b
	- #history
- Their home, the rugged, rain-swept canyon country of the Khasi Hills, was seldom visited by outsiders until very recently. Yet, some of the living bridges are thought locally to be over 500 years old. The claim can’t be conclusively proven without scientific testing, but one thing is certain: the creation of living architecture in Northeast India goes back further than the region’s written history.
  ls-type:: annotation
  hl-page:: 1
  hl-color:: yellow
  id:: 6737e8d7-a2b5-49ee-859f-3c6be3bdc4b4
	- #history #isolated

hls__file 2

research-topic:: Living Root Bridges
tags:: #[[living root bridge]]

- Hally War, a 68-year-old farmer from Siej village, learned the art of creating a jingkieng jri—as the living root bridges are locally known—from his grandfather.
  ls-type:: annotation
  hl-page:: 2
  hl-color:: yellow
  id:: 67239cba-bf66-4cc6-a5fa-ef3052d379e0
	- #generational
- I n the dawn of times, there were sixteen primordial tribes who lived with their creator in their heavenly abode, the kingdom of clouds. One fine day, one of these men looked down and discovered a lush paradise, filled with mesmerizing waterfalls, luxurious jungle, and abundant food. He asked the creator to conceive the jingkiengjriksiar, a mythical “golden bridge” formed by a majestic tree which connected the two worlds, and moved with some human settlers into this idyllic land. This is the kind of story that Hally War heard while growing up in northeastern India, cuddled with his siblings around the fire during the long, cold nights. War, now a 68-year-old farmer from Siej village, belongs to the Khasi tribe for whom the concept of a tree bridge is far more than just a foundational legend.
  ls-type:: annotation
  hl-page:: 2
  hl-color:: yellow
  id:: 67239ce0-dfbb-45e6-9ea1-123df2c8c4ac
	- #folklore #history

Let me know if anything else would help. Thanks in advance for any guidance you could give.

Something like this:

#+BEGIN_QUERY
{
 :query [:find (pull ?b [*]) ?tagname ?content
   :keys child tagname content
   :where
     [?parent :block/page ?page]
     (property ?parent :hl-color "yellow")
     (page-property ?page :research-topic "Living Root Bridges")
     [?parent :block/content ?content]
     [?b :block/parent ?parent]
     [?b :block/refs ?tag]
     [?tag :block/name ?tagname]
 ]
 :result-transform (fn [result] (map (fn [r]
   (update (:child r) :block/properties (fn [p]
     (assoc p
       "tag" (:tagname r)
       "Parent Block" (first (clojure.string/split (:content r) "\n"))
     )
   ) )
 ) (sort-by :tagname result) ) )
}
#+END_QUERY

That works great, thanks so much!

Is there a resource where I can learn how result-transform works? Or is my best approach just to read examples until I figure out the patterns?

  • :result-transform
    • is clojurescript
    • can be learnt through the reference
    • its input/output can be inspected with :view (fn [r] [:pre.code (pprint r)])
  • Examples remain very helpful.
    • Thus also this forum.