How to read a property that its name (keyword) is dynamically formed from the name of a page?

Hi,

I have lurked in the topics to help me come up with a query to put on my type page. I use type as a property to organise my stuff.

My goal was to get a list of pages that are missing the property type, and list them with link.

#+BEGIN_QUERY
{ :title [:b "Pages missing type" ]
:query [:find ?pagename
    :where 
        [?b :block/properties ?prop]
        [?b :block/name _]
        [?b :block/original-name ?pagename]
        (not [?b :block/journal? true])
        (not [(get ?prop :type)])
]
:view (fn [result] (for [r result] [:div [:a.tag.mr-1 {:href (str "#/page/" (clojure.string/replace r "/" "%2F") )} r ] ] ) )
}
#+END_QUERY

This works great (it does list my whiteboards though, which bonus point if you can let me know how to filter them too)

Now what I’d like to do, is to be able to use that query on other property pages. So I have tried to use in/inputs like this:

:query [:find ?pagename
    :in $ ?t
    :where 
        [?b :block/properties ?prop]
        [?b :block/name _]
        [?b :block/original-name ?pagename]
        (not [?b :block/journal? true])
        (not [(get ?prop ?t)])
]
:inputs [:query-page]

but that does not seem to work. Can anyone help me pinpoint where I got things wrong?

Welcome.

  • :query-page and thus ?t carry a string
  • but function get expects a keyword
    • a keyword can be produced e.g. with [(keyword ?t) ?k]
    • then use it like (not [(get ?prop ?k)])
2 Likes

Ahh I figured as much. But, despite being a seasoned programmer, this clojure syntax is just so foreign to me!

Thank you very much!

Could try this for the whiteboard filter:

(not 
  [(get ?prop :ls-type) ?lstype]
  [(keyword "whiteboard-page") ?wb]
  [(= ?lstype ?wb)]
)
1 Like

That seems to be a good way to do it. I’ve replaced that with a not= operator to avoid the big (not ...)

#+BEGIN_QUERY
{ :title [:b "Pages missing ?t" ]
:query [:find ?pagename
    :in $ ?t
    :where 
        [?b :block/properties ?prop]
        [?b :block/name _]
        [?b :block/original-name ?pagename]
        (not [?b :block/journal? true])
        [(keyword ?t) ?k]
        (not [(get ?prop ?k)])

        [(get ?prop :ls-type) ?lstype]
        [(keyword "whiteboard-page") ?wb]
        [(not= ?lstype ?wb)]
]
:inputs [:current-page]
:view :page-link
}
#+END_QUERY

Not sure if all pages have a :ls-type property. If they don’t have it, the query will filter them out too. That’s the reason for using the big (not ).

1 Like

Since you are a seasoned programmer, should keep in mind that:

  • Datalog is even more foreign than Clojure
  • what @Siferiax said should be understood like this:
    • her code:
      (not 
        [(get ?prop :ls-type) ?lstype]    ; a
        [(keyword "whiteboard-page") ?wb] ; b
        [(= ?lstype ?wb)]                 ; c
      )
      
      • means: NOT(a AND b AND c)
        • which is equivalent to: NOT(a) OR NOT(b) OR NOT(c)
    • while your code:
      [(get ?prop :ls-type) ?lstype]    ; a
      [(keyword "whiteboard-page") ?wb] ; b
      [(not= ?lstype ?wb)]              ; c
      
      • means: a AND b AND NOT(c)
  • You may still move [(keyword "whiteboard-page") ?wb] out of the (not), because it is a constant.
2 Likes

Good point. I kinda filtered out that implicit AND out of my mind.

Also if not all pages have the property, that’s going to break indeed.

Yeah the language is indeed very foreign to say the least, I’m still a bit confused about how things are typed (it seems that there are type at least implicitly), and documentation on the format for logseq itself is not very extensive.

Thank you very much both, that has been very informative and helpful!

1 Like

Some helpful resources:

2 Likes

So I’ve tried this:

#+BEGIN_QUERY
{ :title [:b "ls-type" ]
:query [:find ?pagename ?lstype
  :where 
      [?b :block/properties ?prop]
      [?b :block/name _]
      [?b :block/original-name ?pagename]
      [(get ?prop :ls-type) ?lstype]
]
}
#+END_QUERY

The only thing I got was the :whiteboard-page. So that’s our answers for have all pages ls-type.

1 Like