I was unaware that the rule/predicate get
is available within custom rules. So now my looks like that:
#+BEGIN_QUERY
{
:title [:b "Habit total"]
:query
[
:find (count ?datename) ?datename
:in $ ?today %
:where
[?p :page/journal? true] ;; can be omitted?
[?b :block/page ?p]
[?p :block/original-name ?datename]
[?p_today :page/journal? true] ;; can be omitted?
[?b_today :block/page ?p_today]
[?p_today :block/journal-day ?today]
(connected-block ?b ?b_today)
]
:inputs [:today]
:rules [
[(next-day ?d1 ?d2) [(+ 1 ?d1) ?d1_next] [(== ?d1_next ?d2)]]
[(pages-next-day ?p1 ?p2) [?p1 :block/journal? true] [?p2 :block/journal? true] [?p1 :block/journal-date ?d1] [?p2 :block/journal-date ?d2] (next-day ?d1 ?d2)] ;; can check for journal page be omitted?
[(blocks-next-day ?b1 ?b2) [?b1 :block/page ?p1] [?b2 :block/page ?p2] (pages-next-day ?p1 ?p2)]
;;
;; the following two lines have changed
;;
[(test-property ?b ?type ?testval) [?b :block/properties ?props] [(get ?props ?type) ?val] [(== ?val ?testval)]]
[(tracked-block ?b) (test-property ?b :type "tracker") (test-property ?b :test true)]
[(connected-block ?b1 ?b2) (tracked-block ?b1) (tracked-block ?b2) (blocks-next-day ?b1 ?b2)]
[(connected-block ?b1 ?b2) (connected-block ?b1 ?bx) (connected-block ?bx ?b2)]
]
}
#+END_QUERY
When I execute this advanced query in a rather empty graph, logseq seems to freeze. At least, I do not get any error in the console and the block looks like this:
But it doesn’t change over several minutes.
Is the above query consuming to much compute ressources, i.e., inefficient? Or are advanced queries not made for such a task?
EDIT1
According to the task manager, CPU and memory of the logseq process increase after starting this query. CPU goes up to 25-30% and memory slowly increases (100 MB over 5 minutes, so really not much).
EDIT2
I tried to reduce the logical overhead in the above queries. Now, I only want to find the number of consecutive journal pages from today’s journal page. Assume, today is 2023-08-05
and you have additional journal pages for 2023-08-04
, 2023-08-03
, 2023-08-01
, but not for 2023-08-**02**
. I want the query to give out the number 2
as there are two journal pages directly connected to today’s journal page. This is the query I wrote:
#+BEGIN_QUERY
{
:title [:b "Consecutive journal days"]
:query
[
:find (count ?p)
:in $ ?today %
:where
[?p :block/journal? true] ;; we are interested in journal pages
;; todays journal page
[?p_today :block/journal? true]
[?p_today :block/journal-day ?today]
;; ?p should be connected by consecutive daily journal pages to todays journal page
(pages-next-day ?p ?p_today)
]
:inputs [:today]
:rules [
;; test whether the day ?d1 is directly followed by ?d2
[(next-day ?d1 ?d2) [(+ 1 ?d1) ?d1_next] [(== ?d1_next ?d2)]]
;; test whether ?p1 and ?p2 are journal pages and test whether they are directly neighbored
[(pages-next-day ?p1 ?p2) [?p1 :block/journal? true] [?p2 :block/journal? true] [?p1 :block/journal-day ?d1] [?p2 :block/journal-day ?d2] (next-day ?d1 ?d2)]
;; find whether two journal pages are connected by an intermediate journal page ?px
;; uncommenting this line will freeze logseq or run some infinite cycle...
;; [(pages-next-day ?p1 ?p2) (pages-next-day ?p1 ?px) (pages-next-day ?px ?p2)]
]
}
#+END_QUERY
The above query is only asking for the number of yesterday’s journal pages, which is obviously either 1
or 0
. To allow the query to run behind yesterday’s journal page I added this recursive statement [(pages-next-day ?p1 ?p2) (pages-next-day ?p1 ?px) (pages-next-day ?px ?p2)]
in the very end of the :rules
. When I uncomment this rule and run the query, logseq freezes or goes into an infinite cycle.
Based on this observation, I wondered whether logseq or datascript are able to run recursive rules? According to GitHub - tonsky/datascript: Immutable database and Datalog query engine for Clojure, ClojureScript and JS recursive rules are supported. I took a closer look on the mentioned rules there and in mentioned chapter 8 of the learndatalogtoday.org tutorial. It seems that you can “call” the same rule within a new rule definition only once, but I do it twice in the above query. Therefore, I changed the second rule definition into:
[(pages-next-day ?p1 ?p2) [?p1 :block/journal? true] [?px :block/journal? true] [?p1 :block/journal-day ?d1] [?px :block/journal-day ?dx] (next-day ?d1 ?dx) (pages-next-day ?px ?p2)]
and then it works! It gives the correct output and does not run infinitely.
EDIT 3
I came across two new problems.
- The variable in
:block/journal-day
is not a date variable, it is a basic integer. So adding +1 with [(+ 1 ?d1) ?d1_next]
works for within month dates, but is not capable of working across months. For example, 2023-07-31 is 20230731
and naively this would give 2023-07-32 as the next date. Similarly, the date before 2023-08-01 is 2023-08-00 which also does not exist. Does anyone have an idea how to workaround this limitation? I guess the easiest way would be to write a Clojure function that sees problematic dates and adjusts automatically…
- I implemented my original idea now in this query with the correct recursive strategy:
#+BEGIN_QUERY
{
:title [:b "Habit streak"]
:query
[
:find (count ?b) ?b
:in $ ?today %
:where
[?b_today :block/page ?p_today]
[?p_today :block/journal-day ?today]
(connected-block ?b ?b_today)
]
:inputs [:today]
:rules [
[(next-day ?d1 ?d2) [(+ 1 ?d1) ?d1_next] [(== ?d1_next ?d2)]]
[(pages-next-day ?p1 ?p2)
[?p1 :block/journal-day ?d1]
[?p2 :block/journal-day ?d2]
(next-day ?d1 ?d2)]
[(blocks-next-day ?b1 ?b2)
[?b1 :block/page ?p1]
[?b2 :block/page ?p2]
(pages-next-day ?p1 ?p2)]
[(test-property ?b ?type ?testval)
[?b :block/properties ?props]
[(get ?props ?type) ?val]
[(== ?val ?testval)]]
[(tracked-block ?b) (test-property ?b :type "tracker") (test-property ?b :test true)]
[(connected-block ?b1 ?b2)
(tracked-block ?b1)
(tracked-block ?b2)
(blocks-next-day ?b1 ?b2)]
[(connected-block ?b1 ?b2)
(tracked-block ?b1)
(tracked-block ?bx)
(blocks-next-day ?b1 ?bx)
(connected-block ?bx ?b2)]
]
}
#+END_QUERY
It works correctly for tracking between today and yesterday. But it is unable to retrieve information from two or more days ago. I cannot spot the error that I am making. Can someone see the error?