Advanced queries - result-transform and view

Hi there, I’m learning the advanced queries and already read the docs on https://docs.logseq.com/#/page/advanced%20queries,
however I still need to dive into the view and result-transform, coz seems everyone is using them quite good but I’m not understand what they are and how they work, besides, I can’t find any docs for view and result-transform, it would be great if anybody can offer me a specific doc.

Actually most people don’t even touch them, because they are hard (in multiple ways).

There is no detailed documentation for advanced queries, much less for :view and :result-transform .

  • They both:
    • are provided with the results of the previous stage
    • process them with clojurescript
    • pass their own results to the next stage
      • here is the order: :query:result-transform:view → render
  • What they need:
    • Some programming knowledge
      • of the functional paradigm
    • Much reading of examples found in the community
      • Thankfully, plenty of material has been gradually accumulated
        • but it is not organized
    • A lot of practice
      • It is hard to even make them work
        • No mistakes are tolerated
    • Tones of patience
      • It is even harder to get what you want
        • There is no intuitive debugging
  • In other words:
    • they are not for everyone
    • although they are powerful
      • they can do things that are impossible without code
        • Unfortunately, they don’t currently provide the full library of functions.
1 Like

Hello, this is the only page that fits my question, I would like to perform the following query explained in natural language, could you give me some guidelines how to implement it?

  1. search every block has the “mytag” in predefined list property “tags”, for example we could have a result of cardinality N
  2. for each of the N block get the value of a property named “myprop” and add it ( I am obviously thinking about this value as a page because logseq automatically created it ) to a temporary list excluding duplicate ( ie: like a a set in another language without duplicates)
  3. after the foreach we will have a list of cardinality M
  4. the result should be assigned temporary list of cardinality M instead of the former founded block list ( cardinality N )

Thanks

image

  • Do you want a list of the unique values in property myprop:: of pages tagged mytag ?
  • Are these values references or plain text?

Hello ! thanks for quick answer

  1. yes

  2. they are references because when i put in predefined tags property on blocks logseq renders them like a link both I write them in text or with #tagnotation , and you can follow as link

In other programming language is very easy , I spent hours in finding a solution :sweat_smile:

Thank you so much

  • To get a list of unique whole values, try this:
    #+BEGIN_QUERY
    {
     :query [:find ?myprop-vals
       :where
         [?tag :block/original-name "mytag"]
         [?b :block/refs ?tag]
         [?b :block/page ?p]
         [?p :block/properties ?props]
         [(get ?props :tags) ?tags]
         [(contains? ?tags "mytag")]
         [(get ?props :myprop) ?myprop-vals]
     ]
    }
    #+END_QUERY
    
  • Try adding to the above query a proper :view, if you want to get the unique:
    • references:
       :view (fn [vals]
         (for
           [d
             (distinct (flatten (map
               (fn [val]
                 (into [] val)
               )
               vals
             )))
           ]
           [:div d]
         )
       )
      
    • words from within plain text:
       :view (fn [vals]
         (for
           [d
             (distinct (flatten (map
               (fn [val]
                 (clojure.string/split val " ")
               )
               vals
             )))
           ]
           [:div d]
         )
       )
      
1 Like

Hello, sorry for the delay, we had a full week, in the next days I will try

Hello , it partially works , some small fixes were needed but a good starting point !

I answered “yes” at point 1, but it was wrong, I’d have had a list of the unique values in property myprop:: of block tagged mytag ( not pages … )

#+BEGIN_QUERY
{
 :query [:find ?myprop-vals
   :where
     [?tag :block/original-name "mytag"]
     [?b :block/refs ?tag]
     [?b :block/properties ?props]
     [(get ?props :tags) ?tags]
     [(contains? ?tags "mytag")]
     [(get ?props :myprop) ?myprop-vals]
 ]
}
#+END_QUERY

Thanks you, I need to understand better the internal logseq db schema

One more issue, i need to split by regex (clojure.string/split val "\s+,\s+") but I get invalid query

  • Regex is normally done with re-pattern and re-find
  • Where are you trying to use clojure.string/split ?
    • Most clojure functions are not currently supported inside :where
    • They are supported inside :result-transform and :view

in the previous suggested view

:view (fn [vals]
   (for
     [d
       (distinct (flatten (map
         (fn [val]
           (clojure.string/split val " ")
         )
         vals
       )))
     ]
     [:div d]
   )
 )

Check the escaping. You may have to use double backslash \\