Query for Displaying Blocks of Resulting Pages

I’ve been using LogSeq for almost a year and have been loving its ability to sort information and keep track of tasks in a very intuitive way. I have a personal graph where I keep track of lessons I’m learning and helpful resources. I’m trying to see if it’d be feasible to write/edit a novel in LogSeq (where it’s integrated with all my other thoughts and ideas). I currently have scenes and chapters on their own pages with several page properties to help with sorting/querying.

Sample Scene Properties:

scene-number:: 3
chapter-number:: 1
book:: 
characters:: 
setting:: 
description::
word-count::
type:: [[Scene]]

Sample Chapter Properties:

type:: [[Chapter]]
chapter-number:: 1
chapter-title::
word-count::
book:: 

My plan is to have a query on each chapter page to gather all scene pages with a matching chapter-number property and sort them by their scene-number property. This will facilitate easy scene order changing. I have book in there to filter out which book I’m looking for.

I’m having an issue making a query that returns the contents of the scene pages. I can get a list of the pages and their properties, but I’m having a hard time getting the contents of the pages. When I right click on my page title to see the page properties, I don’t see a contents property. Is the file property a page’s equivalent to :block/content? Is there a way to access it and the :db/id property within?

I’ve also thought about querying for each block that has a parent containing the correct chapter-number property value, but I don’t know how to have the displayed scene blocks sorted as they are on the pages. I’d eventually like to have a page to query for the whole book and sort it by scene-number.

@Siferiax I’ve seen several of your in-depth custom queries on this forum. Is this feasible to do with an Advanced query?

I have a rough query that would live on each chapter page below, but it’s not working.

#+BEGIN_QUERY
{ ; Surrounding Block
 :title [:h2 "All Scenes in this chapter"]
 :query [ ; Start Query Block
         :find (pull ?p [*]) 
         :in $ ?current-page
         :where 
         	(page-property ?p :type "scene")
         	(page-property ?p :chapter-number ?current-page)
         ] ; Close Query
 :inputs [:current-page]
}
#+END_QUERY

First of, thanks for the elaborate information ! That really helped tackle this :slight_smile:

So it’s not impossible, just a bit complicated.
Some things to note:

  • property values should be exactly equal for this to work
  • you loose the group by page effect
  • if you have multiple blocks on a scene’s page, those won’t be sorted properly this way

Here’s what it looks like:

Here’s what it looks like in table form, just to show the page names I used.

And here’s the query:

#+BEGIN_QUERY
{:title [:b "Scenes"]
 :inputs [:query-page]
 :query [:find ?scnum (pull ?b [*]) ;return both scene-number and blocks
  :keys scene block ;put find values into key value pairs.
  :in $ ?chapter
  :where
;get the information about the chapter
   [?ch :block/name ?chapter]
   [?ch :block/properties ?chprop]
   [(get ?chprop :book) ?chbook]
   [(get ?chprop :chapter-number) ?chnum]
;find matching scenes
   [?sc :block/properties ?scprop]
   [(get ?scprop :type) ?type]
   [(contains? ?type "Scene")]
   [(get ?scprop :book) ?scbook]
   [(= ?scbook ?chbook)]
   [(get ?scprop :chapter-number) ?sc-chnum]
   [(= ?sc-chnum ?chnum)]
   [(get ?scprop :scene-number) ?scnum]
;get their blocks
   [?b :block/page ?sc]
;exclude properties block
   (not [?b :block/pre-block? true])
 ]
 :result-transform (fn [result] 
  (sort-by 
    (fn [s] (get-in s [:block/properties :scene])) 
    (map 
      (fn [m] 
        (update (:block m) :block/properties 
          (fn [u] (assoc u :scene (get-in m [:scene]) ) )
        )
	  ) 
      result
    )
  )
)
}
#+END_QUERY
1 Like

Wow that you for taking the time to develop this query! I didn’t realize it would be that complex! I’ll need to spend some time digesting the pieces :exploding_head:

My current workflow will have multiple blocks within each Scene page. I want to be able to keep all the actual text of the scene in a “level 1” block and have comments/tasks/notes/references about each paragraph as child blocks. There isn’t a way to query and determine which order blocks appear in the page/file?

I may need to look into a custom JS plugin for this. I think there’s a get_page_tree() function in the LogSeq API I may be able to use to keep/determine the order.

Is there a way to access the :db/id or :block/file properties in a query? Would these give the page structure/block order?

1 Like

You’re welcome.
For the results, if there’s only 1 level 1 block, it will work just fine.
It is having multiple level 1 blocks that will cause issues.

So if your page is

  • this is the scene text
    • this is some references
    • TODO this is a task

That’s fine.
However if it is like

  • this is some text
    • this is a reference
  • this is some other text
    • this is a reference

There will be an issue sorting “this is some text” and “this is some other text”.

:block/file is the db/id of the file if I’m not mistaken.
db/id of the block gets assigned when it is made and so may not lead to a proper sort.