this post was submitted on 01 May 2024
12 points (100.0% liked)

Logseq

557 readers
25 users here now

Logseq is a knowledge management and collaboration platform. It focuses on privacy, longevity, and user control. It is Free Libre Open Source Software (AGPL-licensed).

Logseq offers a range of powerful tools for knowledge management, collaboration, PDF annotation, and task management with support for multiple file formats, including Markdown and Org-mode, and various features for organizing and structuring your notes.

Logseq's Whiteboard feature lets you organize your knowledge and ideas using a spatial canvas with shapes, drawings, website embeds, and connectors. You can visually group and link your notes and external media (such as videos and images), enabling visual thinkers to compose, remix, annotate, and connect content from their knowledge base and emerging thoughts in a new way.

In addition to its core features, Logseq has a growing ecosystem of plugins and themes that enable a wide range of workflows and customization options. Mobile apps are also available, providing access to most of the features of the desktop application. Whether you're a student, a professional, or anyone who values a clear and organized approach to managing your ideas and notes, Logseq is an excellent choice for anyone looking to improve their productivity and streamline their workflow.

founded 2 years ago
MODERATORS
top 5 comments
sorted by: hot top controversial new old
[โ€“] [email protected] 2 points 3 months ago (2 children)

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]
[โ€“] [email protected] 1 points 3 months ago (1 children)

@Deebster I also found this website pretty cool to help me visualize what a regex does. https://regex-vis.com/

[โ€“] [email protected] 1 points 3 months ago (1 children)

@[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!

[โ€“] [email protected] 1 points 3 months ago* (last edited 3 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
[โ€“] [email protected] 1 points 3 months ago

@Deebster Very interesting. While I was reading, I always thought whether I could use regex. Now here it is. Thanks a lot!