Give me all the areas/projects that I use to categorize pages

Hi,

In order to use a little of PARA organization, I tag some pages with properties like

area:: [[Health]]

or

project:: [[Kitchen Remodeling 2022]]

Now, I wanted to have a single page where I would list all projects and areas that I have used over my graph. I don’t want the pages tagged with a specific area/project. It’s the other way around.

I’ve managed to to that using this query (for the areas):

#+BEGIN_QUERY
{
 :title [:h4 "Areas"]
 :query [
         :find (pull ?p [*])
         :where 
         (has-page-property ?p :area)
         ]
 :result-transform (fn [result]
                     (distinct (mapcat (fn [linked-page]
                                         (get-in linked-page [:block/properties :area])
                                         ) result ))
                     )
 :view (fn [result]
         [:div.flex.flex-col
          (for [page result]
            [:a {:href (str "#/page/" page)} page ]
            )
          ]
         )
 }
#+END_QUERY

This query gives me this beautiful and useful list:

it took a while to figure out how to use :result-transform. Almost all the examples I saw just ordered the results, and never transformed the data within.

I hope this helps anyone having trouble using the advanced query. :slight_smile:

Thanks for the sharing!
Also bothered by lack of advanced queries documentation.
Do you have any idea if closure.core functions can be used in query? i experimented with select-keys, but failed to make it right. I find the select-keys from clojure.core - Clojure v1.11 API documentation

Hi Leo!

I’d assume select-keys would work as well. Perhaps you have the change :view a little bit? I only got my query working when I added the :view.

Thanks . I will try on this

I can’t seem to make this work…I am seeing this:

I will share with you what I currently use. I am also following PARA.

I have project pages that all start with namespace Project (e.g. Project/2023 Taxes).
Then I have areas that start with namespace Area (e.g. Area/Finances).

Projects have an area property (e.g area:: [[Area/Finances]]). Notes have a para property that can be a project or an area, but that’s not relevant for the query I will share below.

So the query I have will give me something like this:

And this is the query:

#+BEGIN_QUERY
{ 
 :title [:h1 "Projects by Area"]

 :query [:find  (pull ?p [*])
    :where 
        [?p :block/journal? false]  ; non journal page
         [?p :block/namespace ?ns] 
         [?ns :block/name "project"] ; starts with "Project" namespace
 ]

 :result-transform (fn [result] 
         (group-by (fn [h] (get-in h [:block/properties :area])) result))  ; group projects by area

:view (fn [result]
    (def encode-url (fn [url] (clojure.string/join "%2F" (clojure.string/split url "/"))))
    (def remove-namespace (fn [name] (first (reverse (clojure.string/split name "/")))))
    [:div.flex.flex-col
        (for [[k projects] result]
            (let [area (first k)] [:div [:h2 [:a {:href (str "#/page/" (encode-url area))} (remove-namespace area) ]] 
                 [:ul  
                     (for [proj projects] [:li 
                     [:a {:on-click (fn [_] (call-api "open_in_right_sidebar" (get proj :block/uuid)))} "➡️ "]
                     [:a {:href (str "#/page/" (encode-url (get proj :block/name) "/"))} (str (get-in proj [:block/properties :icon]) " " (remove-namespace (get proj :block/original-name)))]])
            ]])
        )
    ]
)
}
#+END_QUERY
2 Likes

I have changed my query. The problem with the original query is that it works with projects being linked to. However, I have also have some project pages that I’m using to dump information and I never link other pages to that project page. The query I was using was not picking these pages.

Since then, I’ve come up with this query:


#+BEGIN_QUERY
{
 :query [:find (pull ?page [*])
         :where
         (or-join [?page]
                  (and [_ :block/properties ?prop]
                       [(get ?prop :project) ?page1]
                       [(str ?page1) ?page11]

                       [_ :block/refs ?page]
                       [?page :block/original-name ?page2]
                       [(str "#{\"" ?page2 "\"}") ?page22]

                       [(= ?page22 ?page11)]
                       )
                  (and
                    [?page :block/name]
                    [?page :block/properties ?prop3]
                    [?page :block/original-name ?page3-name]
                    [(get ?prop3 :page-type) ?v]
                    (or [(= ?v "Project")] [(contains? ?v "Project")])
                    )

                  )

         ]


 :view (fn [result]
         [:div.flex.flex-col
          (for [page result]
            [:a {:href (str "#/page/" (get page :block/original-name))} (get page :block/original-name) ]
            )
          [:hr]
          ]
         )

Much more complex, I know. I had to dig into Datalog docs and tutorials to wrap my head around it :slight_smile: