Advanced query with "get-else" yields error

I opened a Github issue for this: advanced query with “get-else” yields error · Issue #6184 · logseq/logseq · GitHub

expand the origianl forum post

my example is based on this message: Advanced Query for NOW or due today/overdue - #12 by quor

i’m trying to modify the query and make it also emit blocks that don’t have a marker. in my mind that only needs changing one line:

#+BEGIN_QUERY
{ :query [:find (pull ?b [*])
  :in $ ?today ?tomorrow
  :where
-   [?b :block/marker ?m]
+   [(get-else $ ?b :block/marker "NA") ?m]
    (not [(contains? #{"DONE", "CANCELED"} ?m)])
    [(get-else $ ?b :block/scheduled ?tomorrow) ?scheduled]
    [(get-else $ ?b :block/deadline ?tomorrow) ?deadline]
    (or 
      [(contains? #{"NOW", "DOING"} ?m)]
      [(<= ?scheduled ?today)]
      [(<= ?deadline ?today)])]
:inputs [:today 99990101]
:result-transform (fn [result]
  (sort-by (fn [h]
    (get-in h [:block/scheduled])) result))
:breadcrumb-show? false}
#+END_QUERY

however, this change leads to a query error that i found via the developer tools:

#error {:message “Insufficient bindings: #{?b} not bound in [(get-else $ ?b :block/marker “NA”) ?m]”, :data {:error :query/where, :form [(get-else $ ?b :block/marker “NA”) ?m], :vars #{?b}}}
Error: Insufficient bindings: #{?b} not bound in [(get-else $ ?b :block/marker “NA”) ?m]

i have looked at numerous examples on how get-else can be used and cannot figure out what i’m doing wrong.


logseq: 0.7.8
platform: linux


1 Like

Maybe I am wrong, but if you check this definition of get-else, it says that you need to pass an entity id as input after the database. But in your query, the variable ?b you are passing doesn’t seem to have any entity id in it. So first, you need to initialize it with some ids so that you can use get-else to fetch the :block/marker attribute values from it. For example,

#+BEGIN_QUERY
{:query [:find (pull ?b [*])
         :in $ ?today ?tomorrow
         :where
         [?b :block/page]
         [(get-else $ ?b :block/marker "NA") ?m]
         (not [(contains? #{"DONE", "CANCELED"} ?m)])
         [(get-else $ ?b :block/scheduled ?tomorrow) ?scheduled]
         [(get-else $ ?b :block/deadline ?tomorrow) ?deadline]
         (or 
          [(contains? #{"NOW", "DOING"} ?m)]
          [(<= ?scheduled ?today)]
          [(<= ?deadline ?today)])]
 :inputs [:today 99990101]
 :result-transform (fn [result]
                     (sort-by (fn [h]
                                (get-in h [:block/scheduled])) result))
 :breadcrumb-show? false}
#+END_QUERY

Here, :block/page is an attribute that is used to identify which page a block belongs to. We can use it to fetch all blocks that are not pages.

2 Likes

thank you! this indeed works.

i want to note that to me it’s unexpected that (pull ?b [*]) does not define ?b in the same way that [?b :block/page] does; i.e. the latter appears redundant to me.

i can imagine other beginners who’s first contact with datalog is via logseq might have the same surprise.