• autokludge@programming.dev
      link
      fedilink
      English
      arrow-up
      1
      ·
      edit-2
      6 months ago

      I did a lot of tinkering around recently to get an advanced query working for me which ended up being quite tricky to work through. I have Project pages (eg [[12335]] ) and on journal pages I have job note blocks for specific jobs ie #12335 Notes with a :job property so the block title can change if needed. There are multiple levels of notes / subnotes / tasks here and I was attempting to do the below query before I learned or-join, but the query was fragile & failing if tasks weren’t at a specific indent level. I ended up spending a Sunday afternoon deep diving into this stuff to figure this out.


      • As I understand it, the datomic data model is just a HUUGE list of ‘datoms’ which are super basic [element-id|attribute|value] rows for everything.
      • There is some concept of ‘unifying’ which is a variable that appears twice in a :where represents the same value across all clauses.
      • Something like (or-join) allows you to control this unification to selected sub items.
        • My visualization on the query is a graph of conditions
        • The :find (?task) element is absolutely required
        • There are ‘facts’ you want to satisfy [(get ?prop :job) ?job] [(contains? #{"TODO" "WAITING" "DOING"} ?marker)].
        • ?task → ?prop (through or-join) → ?prop must contain :job with value :current-page
        • . ↳ ?marker -> must be one of TODO / WAITING / DOING
      #+BEGIN_QUERY
      {
        :title [:h3 "📅 Outstanding Tasks"]
        :inputs [:current-page]
        :query [
          :find (pull ?task [*])
          :in $ ?job
          :where
            (or-join [?task ?prop]        ; only care that ?task and ?prop are 'unified' with rest of clauses
             (and
              [?task :block/page ?page]
              [?page :block/properties-text-values ?prop]    ; does page have :job property?
              )
             (and
              [?task :block/parent ?tp]
              [?tp :block/properties-text-values ?prop]    ; does task parent have :job property?
              )
             (and
              [?task :block/parent ?tp]
              [?tp :block/parent ?tpp]
              [?tpp :block/properties-text-values ?prop]    ; does task grand-parent contain :job prop?
              )
             (and
              [?task :block/parent ?tp]
              [?tp :block/parent ?tpp]
              [?tpp :block/parent ?tppp]
              [?tppp :block/properties-text-values ?prop]    ; does task great-grand-parent contain :job prop?
              )
            )
            [(get ?prop :job) ?job]                           ; does one-of ?props from above contain :job <%current page%>?
            [?task :block/marker ?marker]                                   
            [(contains? #{"TODO" "WAITING" "DOING"} ?marker)]  ; ?task:block/marker must match one of these
        ]
        :table-view? false
        :result-transform (fn [result]
            (sort-by (fn [m]
                      (get m :block/marker)) > result
            )
            )
        :breadcrumb-show? false
        :collapsed? false
      }
      #+END_QUERY