Question on Logseq advanced query. Can anybody help here? 😩
I’m no expert in advanced queries, but just to note that you could make things simpler (well, shorter at least) by using a regex to handle all those starts-with lines.
This selects all pages that don’t start with 0-9 or @:
#+BEGIN_QUERY { :title [:h2 "Query Results"] :query [ :find (pull ?p [*]) :where [?p :page/name ?page_name] [(re-pattern "^[^0-9@].*") ?regex] [(re-matches ?regex ?page_name)] ] } #+END_QUERY
You could also extend the regex to handle the “includes _ or -” bit too:
[(re-pattern "^[^0-9@_-][^_-]*") ?regex]
@Deebster Very interesting. While I was reading, I always thought whether I could use regex. Now here it is. Thanks a lot!
@Deebster I also found this website pretty cool to help me visualize what a regex does. https://regex-vis.com/
@[email protected] looks good! I am fluent in regex and SQL and I know some Clojure, but these datalog queries are still a bit of mystery to me… that’s the thing I need to visualise!
@Deebster I came a different route from data analysis (C, R, Python, Rust) but I’m less familiar with databases. I’m still trying to remind myself that Clojure, datalog, and Datomics are different … And some syntax is not available in Logseq so there is that … 😂
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